首页 > 解决方案 > 悬停效果在画布 HTML5 内的路径上

问题描述

我在画布中有一条路径,我想在每个形状上添加悬停效果。当用户将鼠标悬停在形状上时,我想透明形状的背景颜色。到目前为止,我已将悬停功能附加到画布上,但我想将其附加到形状上。

const canvas = document.getElementById('canvas');  
const ctx = canvas.getContext('2d');    
// ctx.fillStyle = "green";
// ctx.fillRect(0,0,150,150)

// ctx.fillStyle = 'green';
// ctx.fillText("hello workd", 0, 10)


ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(350,100)
ctx.lineTo(500,95)
ctx.lineTo(500,130)
ctx.lineTo(350,135)
ctx.lineTo(100,130)
ctx.closePath()
ctx.fillStyle = "green";
ctx.fill()
ctx.lineWidth = 10
ctx.strokeStyle = "red"
ctx.stroke()



ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(350,200)
ctx.lineTo(500,195)
ctx.lineTo(500,230)
ctx.lineTo(350,235)
ctx.lineTo(100,230)
ctx.closePath()
ctx.fillStyle = "green";
ctx.fill()
ctx.lineWidth = 10
ctx.strokeStyle = "red"
ctx.stroke();

canvas.onmousemove = function(e){
    console.log('x', e.clientX)
    console.log('y', e.clientY)
}
<!DOCTYPE html>
<html>
    <style>
     body{
         background: red;
         display: flex;
         justify-content: center;
         align-items: center;
         margin: 0;     
     }
     #canvas {
         background: white
     }
    </style>
<body>
<canvas id="canvas" width="600" height="600"></canvas>
<script src="canvas.js"></script>
</body>
</html>

标签: javascripthtml5-canvas

解决方案


点在路径上 2D

您可以使用isPointInPath()isPointInStroke来检查一个点是否在当前路径上。或者为了更容易,您可以使用Path2D对象来保存路径并将其传递给函数,从而节省每次鼠标移动时创建路径的需要。

例子

下面的示例使用Path2D创建两条路径。然后该事件使用isPointInPath()mousemove检查鼠标是否在路径上。如果路径(1、2 或无)发生变化,则清除画布并重新绘制路径以反映新状态。

const ctx = canvas.getContext('2d'), mouse = {x:0, y:0, overPath: null}; 
const styles = {
     default: {fillStyle: "#0C0", strokeStyle: "#F00", lineWidth: 4},
     over: {fillStyle: "#C008", strokeStyle: "#F0F8", lineWidth: 10},
};
const paths = [
    [100, 50, 350, 50, 500, 45, 500, 80, 350, 85, 100, 80],
    [100, 150, 350, 150, 500, 145, 500, 180, 350, 185, 100, 180],
].map(createPath);
canvas.addEventListener("mousemove", (e) => {
   mouse.x = e.offsetX;
   mouse.y = e.offsetY;
   checkMouseOver(paths);
   canvas.style.cursor = mouse.overPath ? "pointer" : "default"; 
});
function checkMouseOver(paths) {
    var over;
    for(const p of paths) { ctx.isPointInPath(p, mouse.x, mouse.y) && (over = p) }
    if (over !== mouse.overPath) {
        mouse.overPath = over;
        ctx.clearRect(0, 0, 600, 200);
        for (const p of paths) {
            if (p === over) { drawPath(p, styles.over) }
            else { drawPath(p) }
        }
    }
}
function createPath(path) {
    var i = 0, p = new Path2D;
    while (i < path.length) { p.lineTo(path[i++], path[i++]) }
    p.closePath();
    return p;       
}
function drawPath(path, style = styles.default) {
    Object.assign(ctx, style).fill(path);
    ctx.stroke(path);    
}
<canvas id="canvas" width="600" height="200"></canvas>


推荐阅读