在svg中检测鼠标指针经过圆
在svg中检测鼠标指针经过圆 | 马黑黑svg绘制圆,使用 fill 方法画出的是实心圆,使用 stroke 方法画出的是圆环。本帖只讨论鼠标指针经过实心圆的检测方法。我们先用 fill 方法绘制一个圆:
<svg id="sc" width="200" height="200" style="background: gray">
<circle cx="100" cy="100" r="50" fill="lightblue" />
</svg>
这是在 200*200 的灰色底 svg 画布上以(100,100)为圆心,绘制一个半径为 50 的浅蓝色实心圆。现在,我们就来检测鼠标是否经过浅蓝色圆的区域,如果经过,鼠标指针变为手型,否则是默认形状。
具体思路是,鼠标点击的点 p(x,y)与圆心 o 连成线段 op,o→p 方向的直线 op 或 op 的延长线必然与圆周线相交于某一点 k,ok 等于圆的半径 r,我们可以将 op 的长度与圆的半径 r 进行比较,从而判断点 p 是否在圆内。这时,我们可以考虑用勾股定理来完成这个判断,方法是:经过 p 点往X轴方向画一根与Y轴平行的辅助线,与X轴相交于 d 点,我们就得到一个直角三角形 △opd,其中,op 为斜线,od 和 dp 为两条直角线,这两根直角线的长度分别对应于点 p 坐标的 x 和 y 值,我们通过鼠标相关事件可以获得这个xy坐标值。那么,如果两个直角边的长度的平方和小于等于圆半径的平方,说明点 p 在圆内,反之在圆外。这是中小学数学知识的应用,按理应该不难理解,除非大家把中小学数学知识还给了美术老师了。
JS有一个内置数学(Math)函数 pow,用于计算 x 的 y 次幂:
Math.pow(x,y);
设直角线分别为 a、b,斜线为 c ,则 JS 中各条线的平方运算公式分别为:
Math.pow(a,2);
Math.pow(b,2);
Math.pow(c,2);
当然也可以用最原始的运算式子:a*a,b*b,c*c。
知识铺垫到位,现在可以用 JS 编写一个检测函数了:
function isCircle(cx, cy, r, ex, ey) {
return Math.pow(ex - cx, 2) + Math.pow(ey - cy, 2) <= Math.pow(r, 2);
}
函数需要 5 个参数:cx,圆心x坐标,cy,圆心y坐标,r是圆的半径,ex 和 ey 分别是鼠标经过或点击时的x、y坐标。
计算式子中,Math.pow(ex - cx, 2) 里,ex - cx 得出鼠标点击的坐标点的x位置离圆心的距离,其中,ex 我们会通过 offsetX 获取,它的实际数值是从事件源对象(元素)的左边到点击点的水平距离,它减去圆心x坐标值就是三角形直角边水平线段的长度;Math.pow(ey - cy, 2) 同理,ey - cy 得到的是垂直于X轴的直角边的长度;Math.pow(r, 2) 计算半径的平方值,无须解释吧。
上述函数被调用时会返回上述式子的计算结果,如果式子成立,返回真(true),否则返回假(false),这是布尔值,非真即假、非假即真,不存在第三方的值。下面是函数调用实例,检测鼠标经过画布与否并作出相应响应,画布的 id 为 sc:
sc.onmousemove = (e) => {
if(isCircle(100, 100, 50, e.offsetX, e.offsetY)) {
sc.style.cursor = 'pointer';
} else {
sc.style.cursor = 'default';
}
}
鼠标移动代码中,带入的参数里,100 和 100 是圆心xy坐标,50 是圆的半径,后两个值就是鼠标经过或点击时的xy坐标值。如此,鼠标在svg画布上移动时,浅蓝色圆的区域鼠标指针为手型,圆外区域鼠标指针为默认形状。
最后附上完整代码:
<svg id="sc" width="200" height="200" style="background: gray">
<circle cx="100" cy="100" r="50" fill="lightblue" />
</svg>
<script>
sc.onmousemove = (e) => {
if(isCircle(100, 100, 50, e.offsetX, e.offsetY)) {
sc.style.cursor = 'pointer';
} else {
sc.style.cursor = 'default';
}
}
function isCircle(cx, cy, r, ex, ey) {
return Math.pow(ex - cx, 2) + Math.pow(ey - cy, 2) <= Math.pow(r, 2);
}
</script>
关于三角函数的那段比较简单,难的是鼠标经过的点能用offsetX和offsetY直接获取。 红影 发表于 2022-9-5 19:51
关于三角函数的那段比较简单,难的是鼠标经过的点能用offsetX和offsetY直接获取。
offsetX和offsetY是JS内置命令,在现代浏览器中都得到完美支持。它们获取事件源元素——即鼠标经过或点击等的元素——的鼠标指针下的xy坐标值,offsetX 是 点到左边的值,offsetY 是 点到上边的值。 谢谢老师的代码分享,学习!{:4_190:} 梦缘 发表于 2022-9-5 20:07
谢谢老师的代码分享,学习!
这个没啥难度吧 马黑黑 发表于 2022-9-5 19:57
offsetX和offsetY是JS内置命令,在现代浏览器中都得到完美支持。它们获取事件源元素——即鼠标经过或点击 ...
哦,是内置命令,嗯,现在知道了{:4_204:} 红影 发表于 2022-9-5 21:54
哦,是内置命令,嗯,现在知道了
专题介绍过的 马黑黑 发表于 2022-9-5 22:41
专题介绍过的
那会没记住啊,现在能更深地知道点了。 来学习! 红影 发表于 2022-9-6 10:41
那会没记住啊,现在能更深地知道点了。
循序渐进 加林森 发表于 2022-9-6 10:53
来学习!
{:4_190:} 马黑黑 发表于 2022-9-6 12:25
谢啦! 马黑黑 发表于 2022-9-6 12:24
循序渐进
这个原理倒不算难,只是要知道命令熟练运用命令不容易。 红影 发表于 2022-9-6 16:14
这个原理倒不算难,只是要知道命令熟练运用命令不容易。
这要深入 马黑黑 发表于 2022-9-6 16:17
这要深入
是的,要熟悉那些命令。 红影 发表于 2022-9-6 21:00
是的,要熟悉那些命令。
最好掌握 马黑黑 发表于 2022-9-6 21:01
最好掌握
嗯嗯,尽力呗{:4_173:} 红影 发表于 2022-9-6 21:21
嗯嗯,尽力呗
挺好
页:
[1]