原生JavaScript:如何让Canvas圆形不脱离指定路径并设初始端点位置
解决方案
1. 设置圆形初始位置到路径端点
直接将圆形的初始坐标x和y赋值为路径的起点坐标pathStartX和pathStartY,替换原来的固定值即可实现初始位置在路径端点。
2. 检测圆形是否在路径内
利用Canvas的isPointInStroke()方法检测圆形中心是否落在路径的描边区域内。先设置合适的描边宽度,让路径形成足够容纳圆形的通道,每一帧检测圆形位置,若滑出则触发游戏结束。
修改后的完整代码
<html> <head> <style> #canvas { border: 1px solid black; } </style> </head> <body> <div> <canvas id="canvas" width="500" height="500"></canvas> </div> <script> var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); var radius = 10; var strokeWidth = 30; // 路径描边宽度,确保足够容纳圆形 var pathWidth = 200; var pathHeight = 100; var pathStartX = 100; var pathStartY = 200; var pathEndX = 400; var pathEndY = 200; var pathControlX = 250; var pathControlY = 100; var pathControlX2 = 250; var pathControlY2 = 300; var pathColor = "black"; var circleColor = "red"; var score = 0; var startTime = new Date().getTime(); var endTime = startTime + 60000; // 初始化圆形位置到路径起点 var x = pathStartX; var y = pathStartY; var path = new Path2D(); path.moveTo(pathStartX, pathStartY); path.bezierCurveTo(pathControlX, pathControlY, pathControlX2, pathControlY2, pathEndX, pathEndY); context.lineWidth = strokeWidth; context.stroke(path); context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.fillStyle = circleColor; context.fill(); canvas.addEventListener("mousemove", function (event) { var rect = canvas.getBoundingClientRect(); x = event.clientX - rect.left; y = event.clientY - rect.top; }); function draw() { context.clearRect(0, 0, canvas.width, canvas.height); // 设置描边宽度并绘制路径 context.lineWidth = strokeWidth; context.stroke(path); context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.fillStyle = circleColor; context.fill(); // 检测圆形是否滑出路径 if (!context.isPointInStroke(path, x, y)) { alert("Game Over! Your score is " + score); clearInterval(interval); return; } // 到达终点生成新路径逻辑 if (x > pathEndX - radius && x < pathEndX + radius && y > pathEndY - radius && y < pathEndY + radius) { score++; pathStartX = pathEndX; pathStartY = pathEndY; pathEndX = Math.floor(Math.random() * (canvas.width - pathWidth)) + pathWidth; pathEndY = Math.floor(Math.random() * (canvas.height - pathHeight)) + pathHeight; pathControlX = Math.floor(Math.random() * canvas.width); pathControlY = Math.floor(Math.random() * canvas.height); pathControlX2 = Math.floor(Math.random() * canvas.width); pathControlY2 = Math.floor(Math.random() * canvas.height); path = new Path2D(); path.moveTo(pathStartX, pathStartY); path.bezierCurveTo(pathControlX, pathControlY, pathControlX2, pathControlY2, pathEndX, pathEndY); x = pathStartX; y = pathStartY; } // 时间结束逻辑 if (new Date().getTime() > endTime) { alert("Time Up! Your score is " + score); clearInterval(interval); } } var interval = setInterval(draw, 10); </script> </body> </html>
关键修改说明
- 初始位置设置:将
x和y的初始值直接设为pathStartX和pathStartY,确保圆形从路径端点开始。 - 路径描边宽度:新增
strokeWidth变量,设置为30(可根据需求调整),让路径形成足够容纳圆形的通道。 - 滑出检测:在
draw函数中加入!context.isPointInStroke(path, x, y)判断,一旦圆形中心不在路径描边区域内,立即触发游戏结束。 - 优化路径绘制:每次绘制路径前都设置
lineWidth,确保新生成的路径也有正确的描边宽度。
内容的提问来源于stack exchange,提问作者Chloe
相关产品推荐
相关产品推荐

