如何通过鼠标事件在Canvas上绘制多个圆形
Canvas多圆形/椭圆绘制问题修复
问题核心:每次鼠标拖动时调用ctx.clearRect(0,0,canvas.width,canvas.height)清空了整个画布,且未保存已绘制完成的图形数据,导致画布始终仅显示当前拖动的图形。
修复方案:通过数组保存已完成的图形参数,每次重绘时先绘制所有历史图形,再绘制当前临时图形。修改后的完整代码如下:
<canvas id="canvas" width="800" height="500"></canvas>
//Canvas var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); //Variables var canvasx = $(canvas).offset().left; var canvasy = $(canvas).offset().top; var last_mousex = last_mousey = 0; var mousex = mousey = 0; var mousedown = false; // 存储已完成的椭圆/圆形参数 var drawnCircles = []; //Mousedown $(canvas).on('mousedown', function(e) { last_mousex = parseInt(e.clientX - canvasx); last_mousey = parseInt(e.clientY - canvasy); mousedown = true; }); //Mouseup $(canvas).on('mouseup', function(e) { if (mousedown) { // 计算当前椭圆的参数:圆心、x半径、y半径 var rx = Math.abs(mousex - last_mousex) / 2; var ry = Math.abs(mousey - last_mousey) / 2; var cx = last_mousex + rx; var cy = last_mousey + ry; // 仅当半径大于0时保存(避免点击无拖动的情况) if (rx > 0 && ry > 0) { drawnCircles.push({ cx: cx, cy: cy, rx: rx, ry: ry }); } } mousedown = false; }); //Mousemove $(canvas).on('mousemove', function(e) { mousex = parseInt(e.clientX - canvasx); mousey = parseInt(e.clientY - canvasy); if(mousedown) { ctx.clearRect(0,0,canvas.width,canvas.height); // 绘制所有已保存的椭圆/圆形 drawnCircles.forEach(function(circle) { ctx.beginPath(); ctx.ellipse(circle.cx, circle.cy, circle.rx, circle.ry, 0, 0, 2 * Math.PI); ctx.strokeStyle = 'black'; ctx.lineWidth = 5; ctx.stroke(); }); // 绘制当前拖动的临时椭圆/圆形 var rx = Math.abs(mousex - last_mousex) / 2; var ry = Math.abs(mousey - last_mousey) / 2; var cx = last_mousex + rx; var cy = last_mousey + ry; ctx.beginPath(); ctx.ellipse(cx, cy, rx, ry, 0, 0, 2 * Math.PI); ctx.strokeStyle = 'black'; ctx.lineWidth = 5; ctx.stroke(); } });
关键改动说明:
- 新增
drawnCircles数组,用于存储每个已完成图形的圆心坐标、x轴半径、y轴半径 - 鼠标松开时计算当前图形参数并保存到数组,同时过滤掉无拖动的点击操作
- 鼠标拖动时,先清空画布,再绘制所有历史图形,最后绘制当前临时图形
- 替换原有的
scale缩放绘制逻辑,改用ctx.ellipse()原生方法直接绘制,代码更简洁易维护
内容的提问来源于stack exchange,提问作者Mainboard
相关产品推荐
相关产品推荐

