javascript - 悬停效果在画布 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>
解决方案
点在路径上 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>
推荐阅读
- android - 如何结合事件“setOnClickListener”和“向右滑动”或“向左滑动”?
- postgresql - Postgresql JDBC 在查询中使用接收到的变量
- r-exams - 如何修复 R/exams 错误“找不到函数答案列表”
- apex - 返回地图中每门课程的学生记录列表。从构造函数调用此方法
- sql - SQL Multi Conditional CASE WHEN 问题
- android - Google Play Android 应用内部测试 - 内部测试人员未显示更新按钮
- node.js - NestJS typeORM如何在存储库上创建多个保存方法
- python - 是否可以在日期不是数据框索引的 groupby() 之后应用seasonal_decompose()?
- python - Python - 将字符串转换为日期时间对象
- c - 如何让我的程序连续运行,同时返回子进程?