Fabric.js 图形绘制后自由绘图异常:线条从图形中间起始
解决Fabric.js切换绘图模式后线条从正方形中心开始的问题
这个问题我之前也踩过类似的坑,本质是切换绘图模式时Fabric.js的内部状态没有被正确重置——当你画完正方形后,Canvas还保留着之前形状的相关坐标信息,切换到自由绘图模式时就会“跑偏”。下面给你具体的解决思路和修正代码:
问题根源
当你先绘制正方形(非自由绘图模式),再开启isDrawingMode = true时,Fabric.js没有自动清除之前绘制形状时的临时状态(比如形状的中心点坐标),导致自由绘图的起始点被错误绑定到了正方形的中心。
修复步骤
- 动态控制绘图模式:不要一开始就固定
isDrawingMode,而是根据当前选中的工具(正方形/铅笔)来切换。 - 切换工具时重置状态:每次切换工具,都要清除Canvas的选中对象、重置临时绘图状态。
- 分离不同工具的事件逻辑:把正方形绘制和自由绘图的逻辑分开,避免互相干扰。
修正后的代码示例
var functouse = "square"; // 初始设为正方形工具,可按需调整 var pensize = 5; var pencolour = "#000000"; var fillcolour = "#ffffff"; var canvas = new fabric.Canvas('sketchpad', { isDrawingMode: false, // 初始关闭自由绘图模式 transparentCorners: false }); canvas.selection = false; // 切换工具的函数(可绑定到按钮点击事件) function switchTool(tool) { functouse = tool; // 清除当前选中对象,彻底重置状态 canvas.discardActiveObject(); // 根据工具类型切换绘图模式 if (tool === "pencil") { canvas.isDrawingMode = true; // 配置铅笔样式 canvas.freeDrawingBrush.width = pensize; canvas.freeDrawingBrush.color = pencolour; } else { canvas.isDrawingMode = false; } canvas.renderAll(); } // 鼠标按下事件处理 canvas.on('mouse:down', function(e) { if (functouse === "square" && !canvas.isDrawingMode) { var pointer = canvas.getPointer(e.e); // 创建初始矩形(后续拖动调整为正方形) var square = new fabric.Rect({ left: pointer.x, top: pointer.y, width: 0, height: 0, fill: fillcolour, stroke: pencolour, strokeWidth: pensize }); canvas.add(square); canvas.setActiveObject(square); // 鼠标拖动时调整正方形大小(保持宽高一致) var onMouseMove = function(e) { var pointer = canvas.getPointer(e.e); var size = Math.max(Math.abs(pointer.x - square.left), Math.abs(pointer.y - square.top)); square.set({ width: size, height: size, left: pointer.x < square.left ? pointer.x : square.left, top: pointer.y < square.top ? pointer.y : square.top }); canvas.renderAll(); }; // 鼠标松开时移除临时事件监听 var onMouseUp = function() { canvas.off('mouse:move', onMouseMove); canvas.off('mouse:up', onMouseUp); }; canvas.on('mouse:move', onMouseMove); canvas.on('mouse:up', onMouseUp); } });
关键说明
- 切换工具时调用
canvas.discardActiveObject():彻底清除之前选中的形状对象,避免其坐标残留影响自由绘图的起始点。 - 严格区分
isDrawingMode状态:只有使用铅笔工具时才开启自由绘图模式,绘制形状时必须关闭该模式,两种模式不能同时生效。 - 单独封装形状绘制逻辑:把正方形的绘制(按下、拖动、松开)事件单独处理,和自由绘图模式完全隔离,避免状态互相干扰。
这样修改后,你切换到铅笔模式时,线条就会从鼠标点击的位置开始,不会再从正方形中心出发啦~
内容的提问来源于stack exchange,提问作者user2664108
相关产品推荐
相关产品推荐

