You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过鼠标事件在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:30:46