canvas如何实现鼠标hover时部分高亮模糊

图片描述

如上图所示,如何实现鼠标移动到两个分开的圆环时给当前圆环添加阴影效果,我现在实现的效果是鼠标hover时,高亮了整个canvas,请问各位大佬如何解决该问题?
我实现的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas环形图01</title>
    <style type="text/css">
        #canvas {
            margin: 100px auto;
        }

    </style>
</head>
<body>
    
    <canvas id="canvas" width="200" height="300"></canvas>

    <script type="text/javascript">

        function draw(options) {
            var oBox = document.getElementById(options.id);
            var ctx = oBox.getContext('2d');
            
            var sCenter = oBox.width / 2;
            var txtY01 = sCenter - 10;
            var txtY02 = sCenter + 10;
            
            var cWidth = oBox.width;
            var cHeight = oBox.height;
            ctx.clearRect(0, 0, cWidth, cHeight);
            var cBegain = 0;
            var cEnd = Math.PI * 2;
            
            ctx.textAlign = 'center';
            ctx.font = 'normal normal 16px Microsoft YaHei';
            ctx.fillStyle = '#666';
            ctx.fillText(options.text[0], sCenter, txtY01);

            ctx.textAlign = 'center';
            ctx.font = 'normal normal 14px Microsoft YaHei';
            ctx.fillStyle = '#ccc';
            ctx.fillText(options.text[1], sCenter, txtY02);

            ctx.lineCap = options.lineCap;
            ctx.strokeStyle = options.color;
            ctx.lineWidth = options.lineWidth[0];

            ctx.beginPath();
            const begain01 = cBegain+options.gap[0];
            const end01 = (cEnd * options.angle[0]) - cBegain - options.gap[0];
            ctx.strokeStyle = '#A8B9C9';
            ctx.arc(sCenter, sCenter, options.radius[0], begain01, end01, false);
            ctx.stroke();
            
            // 环形阴影
            ctx.shadowColor = "#FFD38E";
            ctx.shadowOffsetX = options.shadow ? 5 : 0;
            ctx.shadowBlur = 8;

            ctx.lineCap = options.lineCap;
            ctx.strokeStyle = options.color;
            ctx.lineWidth = options.lineWidth[1];

            ctx.beginPath();
            const begain02 = cBegain-options.gap[1];
            const end02 = -(cEnd * options.angle[1]) + options.gap[1];
            ctx.strokeStyle = options.color;
            ctx.arc(sCenter, sCenter, options.radius[1], begain02, end02, true);
            ctx.stroke();
        }

        draw({
            id: 'canvas',
            color: '#FF9C00',
            angle: [0.3, 0.7],
            radius: [80, 80],
            lineWidth: [20, 20],
            text: [1000, '发送总人数'],
            gap: [0.02, 0.02],
            shadow: false
        });

        var oBox = document.getElementById('canvas');
        oBox.onmousemove = (e) => {
            draw({
                id: 'canvas',
                color: '#FF9C00',
                angle: [0.3, 0.7],
                radius: [80, 80],
                lineWidth: [20, 20],
                text: [1000, '发送总人数'],
                gap: [0.02, 0.02],
                shadow: true
            });
        }

    </script>
</body>
</html>
阅读 11.7k
7 个回答

canvas 不像 svg ,它对外是一个整体,你只能通过具体的坐标数据,自己计算鼠标位于内部哪些“元素”上面。而具体的算法,也不是那么直观的,可以去找找 echarts 实现方面的东西参考。

使用zrender.js把

canvas绘制完之后就相当于一个可更改的图片。你可以覆盖绘制像素点即可。

计算鼠标坐标是否在相应区域内

建议用echarts.或者就用echarts的基本库,zrender可能更方便一些。
前一段时间,也稍微折腾过canvas.
按照思路,要对整个canvas进行hover监听,然后还要获取鼠标在canvas上的相对位置,与不同圆环的位置进行匹配(也就是要一个数组,里面是 圆环对象)。
然后再requestAnimation进行整体重绘。
稍微有点麻烦。

其实单单做这个的话原理很简单:

1.将每个绘制的图形保存为对象
2.用观察者模式来为相应的对象注册事件
3.鼠标事件来发布消息并传入位置进行判断。

唯一需要注意的是在经过变形后的图形(旋转,斜切,放大)等,各顶点的位置,至于判断某一点是否在图形内请用射线法来实现,对于圆形的判断方法更简单,计算点与圆心的距离就行。

新手上路,请多包涵

建议使用e-charts插件,方便快捷,效果好,自己写比较耗时,大体原理前面的人都说的差不多了,给整个画布添加鼠标事件,获取相对坐标,判断位置

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题