如何在页面上实现一个圆形的可点击区域?

最近看到一个面试题:如何在页面上实现一个圆形的可点击区域,搜集了网上的一些 idea,并进行实现,在此进行归纳整理。

border-radius(HTML5)

首先想到的就是用 border-radius 来实现圆形,同时将鼠标设置为 cursor: pointer

border-radiusCSS3 的属性,它用来向 div 元素添加圆角边框。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>实现圆形的可点击区域</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#circle{
width: 100px;
height: 100px;
line-height: 100px;
margin: 120px auto;
border-radius: 50%;
background: red;
cursor: pointer;
text-align: center;
color: white;
}
</style>
</head>
<body>
<div id="circle">可点击区域</div>
<script type="text/javascript">
window.onload = function(){
var oC = document.getElementById('circle');
oC.onclick = function(){
alert('Yeap!');
}
}
</script>
</body>
</html>

上面代码的显示结果如下图:红色圆即为圆形可点击区域,在此区域内点击,则会弹出 "Yeap!",在页面其他地方点击则不会有任何效果。
方法一实现效果图

map + area

这种方法完全依赖于 HTML 标签来解决这个问题。
<map> 标签用来定义一个客户端图像映射(带有可点击区域的一副图像);
<area> 标签用来定义图像映射中的区域,area 元素永远嵌套在 map 元素内部;

注意: <img> 标签中的 usemap 属性可引用 <map> 中的 idname 属性(具体引用的是哪一个取决于浏览器),所以,一般我们会同时向 <map> 添加 idname 属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title>实现圆形的可点击区域</title>
</head>
<body>
<img src="1.png" width="299" height="299" border="0" usemap="#Map" />
<map name="Map" id="Map">
<area shape="circle" coords="150,150,150" href="canvas.html" target="_blank"/>
</map>
</body>
</html>

以上代码中,<img>usemap 属性值 = '#' + <map>idname 属性的值。标签 <area> 中,属性 shape 表示定义区域的形状,coords 属性定义可点击区域的坐标。其最终显示结果如下图所示,当点击圆形图片区域时,会在空白页面打开 canvas.html 页面;在页面其他区域点击,则没有任何效果。
方法二实现效果图

纯 JS 实现

该方法主要就是通过判断鼠标点击的点是否在圆形区域内来实现,为了使显示效果更加明显,借用了方法一中的 border-radius 来进行界面的显示效果。
假设有两个点 A(x1,y1)B(x2,y2),求两个点之间的距离 d
var d = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

现假设可点击区域的圆心为 (100,100),半径 r = 50,根据鼠标点击的位置与圆心的距离,来判断是否在可点击区域内。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title>实现圆形的可点击区域</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
body{
background: #000;
}
div{
position: absolute;
left: 50px;
top: 50px;
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
line-height: 100px;
text-align: center;
color: white;
}
</style>
</head>
<body>
<div>可点击区域</div>
<script type="text/javascript">
window.onload = function(){
// 假设圆心为(100,100),半径r = 50
document.onclick = function(event){
var event = event || window.event;
var x0 = 100;
var y0 = 100;
var r = 50;
var x1 = event.clientX;
var y1 = event.clientY;
var dis = Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
if(dis <= r){
alert("Yeap~");
}else{
alert("Oh,no!");
}
}
}
</script>
</body>
</html>

以上代码的显示结果如下图所示,当鼠标在页面红色可点击区域圆内点击时,会弹出 "Yeap!";若在页面其他区域点击,则会弹出 "Oh,no!"
方法三实现效果图
方法三实现效果图

canvas 实现

canvasHTML5 提供的,用来在浏览器中创建图形,它可以通过 JavaScript 绘制 2D 图形。

因此我们可以通过用 canvas 在浏览器中绘制一个圆形,然后给这个圆形添加区域内点击事件即可实现。(其实这种方法跟方法三类似,只是用 canvas 来绘制圆形)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title>实现圆形的可点击区域</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
body{
background: #000;
}
#drawing{
background: #fff;
}
</style>
</head>
<body>
<canvas id="drawing" width="400" height="400"></canvas>
<script type="text/javascript">
window.onload = function(){
var drawing = document.getElementById('drawing');
var context = drawing.getContext('2d');
var c = new Shape(100,100,50);
drawing.onmousedown = function(event){
var event = event || window.event;
var point = {
x: event.clientX - drawing.offsetLeft,
y: event.clientY - drawing.offsetTop
};
c.reDraw(point);
}
c.click = function(){
alert('Congratulation!');
}
function Shape(x,y,r){
this.x = x;
this.y = y;
this.r = r;
context.fillStyle = "red";
context.beginPath();
context.arc(this.x,this.y,this.r,0,2*Math.PI,false);
context.closePath();
context.fill();
}
Shape.prototype.reDraw = function(point){
context.fillStyle = "red";
context.beginPath();
context.arc(this.x,this.y,this.r,0,2*Math.PI,false);
context.closePath();
context.fill();
if(context.isPointInPath(point.x,point.y)){
this.click();
}
}
}
</script>
</body>
</html>

以上代码的显示结果如下图所示,当鼠标在圆形区域内点击时,会弹出 "Congratulation!";在页面其他区域点击鼠标,则不会有任何效果。
方法四实现效果图

如果你有别的实现方法,欢迎交流~

您的支持将鼓励我继续创作!