如何在Canvas上绘制红圈移动轨迹且避免蓝圈移动时留下痕迹
Canvas 单元素轨迹保留实现方案
需求说明
已经实现的基础效果:蓝色小圆围绕红色大圆旋转,按住鼠标时红色大圆会沿蓝圈当前指向的方向移动。需要实现的效果是:仅保留红圈的移动轨迹,蓝圈旋转/移动时不留任何痕迹。
核心实现思路
不需要删除clearRect清屏逻辑,换轨迹存储的思路即可实现:
- 新增一个数组专门存储红圈移动过程中的所有历史坐标点
- 每次动画帧执行时先清屏,再按顺序绘制所有历史轨迹点、当前红圈、当前蓝圈
- 只有按住鼠标红圈移动时,才往轨迹数组中新增坐标点
这样清屏只会清除上一帧的临时内容,历史轨迹会通过数组重绘永久保留,蓝圈每次只绘制最新位置,不会留下痕迹。
修改后完整代码
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Canvas basics</title> <link rel="stylesheet" href="style.css"> </head> <body> <canvas id="canvas1"></canvas> <script src="script.js"></script> </body> </html>
CSS
#canvas1{ position: absolute; top:0; left: 0; width: 100%; height: 100%; }
JavaScript
const canvas = document.getElementById('canvas1'); const ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; let positionX = 100; let positionY = 100; let X = 50; let Y = 50; let angle = 0; let mouseButtonDown = false; // 新增:存储红圈轨迹点的数组 const trailPoints = []; document.addEventListener('mousedown', () => mouseButtonDown = true); document.addEventListener('mouseup', () => mouseButtonDown = false); // 新增:绘制红圈轨迹的方法 function drawTrail() { ctx.fillStyle = 'rgba(255,0,0,0.3)'; // 半透明红色轨迹,也可以调整为不透明 trailPoints.forEach(point => { ctx.beginPath(); ctx.arc(point.x, point.y, 20, 0, Math.PI*2); // 轨迹点大小可自定义调整 ctx.closePath(); ctx.fill(); }); } function circle(){ ctx.fillStyle = 'red'; ctx.beginPath(); ctx.arc(X, Y, 20, 0, Math.PI*2); ctx.closePath(); ctx.fill(); } function direction(){ ctx.fillStyle = 'blue'; ctx.beginPath(); ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI*2); ctx.closePath(); positionX = 35 * Math.sin(angle); positionY = 35 * Math.cos(angle); ctx.fill(); } function animate(){ if (mouseButtonDown) { X += positionX / 10; Y += positionY / 10; // 新增:按住鼠标移动时,记录当前红圈坐标到轨迹数组 trailPoints.push({x: X, y: Y}); } else { angle += 0.1; } ctx.clearRect(0,0, canvas.width, canvas.height); // 绘制顺序:先画轨迹,再画当前红圈,最后画蓝圈,保证层级正确 drawTrail(); circle(); direction(); requestAnimationFrame(animate); } animate();
如果觉得离散点组成的轨迹有锯齿,也可以把轨迹绘制逻辑改成用lineTo绘制连续线段,效果会更顺滑。
内容的提问来源于stack exchange,提问作者mahesh
相关产品推荐
相关产品推荐

