纯Vanilla JS实现Canvas单图形删除:保留指定图形并移除目标图形的技术问询
嘿,我明白你遇到的Canvas难题了——既要让红色光标流畅跟随鼠标,又要保留绘制的蓝色图形,还要能单独删除它们对吧?咱们不用第三方库,纯Vanilla JS就能搞定,核心思路是用数组管理所有绘制的图形,每帧清空画布后重新渲染所有元素,这样就能解决你说的两个问题,同时实现单个图形删除功能。
问题根源分析
你之前的两个问题本质上是同一个原因:没有对已绘制的图形进行持久化管理:
- 清画布时没重新绘制已有的蓝色图形,导致它们被清除
- 不清画布时,红色光标每次移动都重新绘制,留下拖影
完整解决方案代码
先给你看修复后的完整代码,我会一步步解释关键改动:
<canvas id="canvas-pl-c-canvas"></canvas>
*{ margin: 0; padding: 0; box-sizing: border-box; } #canvas-pl-c-canvas:hover{ cursor: none; }
const canvas = document.getElementById('canvas-pl-c-canvas'); const c = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; // 定义图形类,保持你的原有逻辑 class Shape { constructor(x, y, radius, color) { this.x = x; this.y = y; this.radius = radius; this.color = color; } draw() { c.beginPath(); c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); c.fillStyle = this.color; c.fill(); } update(nx, ny) { this.x = nx; this.y = ny; } } // 初始化红色光标 const x = canvas.width / 2; const y = canvas.height / 2; const cursor = new Shape(x, y, 10,'red'); // 用数组存储所有绘制的蓝色图形 let shapes = []; let isDrawing = false; // 统一渲染函数:清空画布 → 绘制所有蓝色图形 → 绘制红色光标 function render() { c.clearRect(0, 0, canvas.width, canvas.height); // 遍历数组绘制所有蓝色图形 shapes.forEach(shape => shape.draw()); // 绘制红色光标 cursor.draw(); } // 鼠标移动事件:更新光标位置,绘制时添加新图形 addEventListener('mousemove', (e) => { cursor.update(e.clientX, e.clientY); if(isDrawing){ // 按住左键时,创建新蓝色图形并加入数组 const newShape = new Shape(e.clientX, e.clientY, 10, 'blue'); shapes.push(newShape); } // 每次移动都重新渲染 render(); }) // 鼠标按键事件:控制绘制状态 canvas.addEventListener('mouseup', () => { isDrawing = false; }) canvas.addEventListener('mousedown', () => { isDrawing = true; }) // 右键删除单个图形:判断点击位置与图形的距离 canvas.addEventListener('contextmenu', (e) => { e.preventDefault(); // 阻止默认右键菜单 const clickX = e.clientX; const clickY = e.clientY; // 过滤数组:移除距离点击位置小于半径的图形 shapes = shapes.filter(shape => { const distance = Math.sqrt(Math.pow(clickX - shape.x, 2) + Math.pow(clickY - shape.y, 2)); return distance > shape.radius; }); // 删除后重新渲染 render(); })
关键改动解释
图形数组管理:
- 新增
shapes数组来存储所有绘制的蓝色图形,这样每帧渲染时可以重新绘制它们,解决清画布丢失图形的问题 - 把原来的
Player类改名为Shape,更贴合它的用途
- 新增
统一渲染函数:
- 写了
render函数,负责清空画布、绘制所有蓝色图形、绘制红色光标,这样所有需要刷新画布的场景都可以调用它,避免重复代码
- 写了
修复光标拖影:
- 每次鼠标移动都调用
render函数,先清空画布再重新绘制所有元素,红色光标就不会留下拖影了
- 每次鼠标移动都调用
单个图形删除功能:
- 监听右键点击事件,阻止默认菜单弹出
- 计算点击位置和每个蓝色图形的距离(用勾股定理),如果距离大于图形半径,就保留这个图形,否则移除
- 过滤后的数组重新赋值给
shapes,然后调用render刷新画布,实现单个图形删除
额外优化建议
- 可以调整蓝色图形的半径(我改成了10,和红色光标一致,你可以改回300)
- 如果需要删除特定图形,还可以给每个
Shape实例加唯一ID,通过ID精准删除 - 可以添加鼠标按下时的初始绘制,避免移动才开始画
这样你的需求就都满足了:红色光标流畅跟随,按住左键绘制蓝色图形,右键点击单个蓝色图形就能删除,而且不会影响其他图形~
内容的提问来源于stack exchange,提问作者user16018534
相关产品推荐
相关产品推荐

