Fabric.js设置originX/originY为center时多边形绘制出现位移问题
解决Fabric.js中设置originX/Y为"center"时多边形绘制位移的问题
这个问题的核心是原点基准改变后,多边形的坐标计算逻辑没有同步调整。当originX/Y从"left"/"top"改为"center"时,Fabric.js会以多边形的中心作为位置计算的基准点,而你在绘制过程中还是直接使用鼠标的原始坐标来更新点,导致最终生成的多边形位置偏移。
下面是修复后的实现思路和代码:
关键修复点
- 在绘制过程中,动态更新多边形点的时候,需要基于当前多边形的中心原点来计算坐标偏移;
- 最终创建正式多边形对象时,确保位置和点坐标的基准统一为"center";
- 移除绘制过程中临时对象的坐标偏移(比如辅助圆点的top/left计算)。
修改后的完整代码
var canvas = window._canvas = new fabric.Canvas('c'); draw_polygon(1); function draw_polygon(id){ editandoPoligono = true; canvas.selection=false; var mode = "add", currentShape; var puntos; newColor = "red"; canvas.observe("mouse:move", function (event) { var pos = canvas.getPointer(event.e); if (mode === "edit" && currentShape) { // 启用center原点 currentShape.originX = "center"; currentShape.originY = "center"; var points = currentShape.get("points"); // 基于中心原点计算当前鼠标位置对应的点坐标 const centerX = currentShape.left; const centerY = currentShape.top; points[points.length - 1].x = pos.x - centerX; points[points.length - 1].y = pos.y - centerY; currentShape.set({ points: points }); canvas.renderAll(); } }); canvas.observe("mouse:down", function (event) { var pos = canvas.getPointer(event.e); if (mode === "add") { // 初始多边形的点基于中心原点计算(第一个点为(0,0),第二个点偏移1px) var obj = new fabric.Polygon([{ x: 0, y: 0 }, { x: 1, y: 1 }], { fill: newColor, objectCaching: false, selectable: false, id: id, olvidar: "olvidar", strokeWidth: 0, originX: "center", originY: "center", left: pos.x, top: pos.y }); var circ = new fabric.Circle({ id: "guiaPol", evented: false, selectable: false, top: pos.y, left: pos.x, radius: 5, fill:"black", perPixelTargetFind: true, originX: "center", originY: "center" }); currentShape = obj; canvas.add(currentShape); canvas.add(circ); newColor= currentShape.get('fill'); mode = "edit"; } else if (mode === "edit" && currentShape && currentShape.type === "polygon") { currentShape.originX="center"; currentShape.originY="center"; var points = currentShape.get("points"); const centerX = currentShape.left; const centerY = currentShape.top; // 基于中心原点添加新的点坐标 points.push({ x: pos.x - centerX , y: pos.y - centerY }); puntos = points; currentShape.set({ points: points }); var circ = new fabric.Circle({ id: "guiaPol", evented: false, selectable: false, top: pos.y, left: pos.x, radius: 5, fill: "black", perPixelTargetFind: true, originX: "center", originY: "center" }); canvas.add(circ); canvas.renderAll(); } }); function pararCreacion(){ if (mode === 'edit' || mode === 'add') { mode = 'normal'; // 基于中心原点创建最终的多边形 currentShape = new fabric.Polygon(puntos,{ id:id, originY: "center", originX: "center", fill: newColor, type: 'polygon', nombre: 'Objeto_' + id, perPixelTargetFind: true, strokeWidth: 0, left: currentShape.left, top: currentShape.top }); var circleObjects = []; canvas.forEachObject(function (o) { if (o.id == "guiaPol") { circleObjects.push(o); } }); canvas.remove(...circleObjects); canvas._objects.pop(); currentShape.nombre = 'Objeto_'+id; if(currentShape.get('points').length>4){ canvas.add(currentShape); // 全局设置为center原点(根据你的需求) fabric.Object.prototype.originX ="center"; fabric.Object.prototype.originY ="center"; currentShape.set({ selectable: true }); }else{ alert("Error"); } canvas.selection=true; editandoPoligono = false; canvas.renderAll(); } currentShape = null; } canvas.on("mouse:dblclick", pararCreacion); };
修复逻辑解释
- 初始多边形创建:把初始点设为
[{x:0,y:0}, {x:1,y:1}],同时将多边形的left和top直接设为鼠标点击的位置(因为origin是center,所以这个位置就是多边形的中心)。 - 鼠标移动更新点:计算鼠标位置相对于多边形中心的偏移量,作为点的坐标值,而不是直接用鼠标的原始坐标。
- 添加新点:同样基于多边形中心计算偏移量来添加新点,保证所有点的坐标都是相对于中心原点的。
- 最终多边形创建:保持origin为center,继承临时多边形的left和top位置,确保视觉上和绘制过程一致。
这样修改后,即使originX/Y设为"center",多边形的绘制位置也会和鼠标操作完全匹配,不会出现位移问题。
内容的提问来源于stack exchange,提问作者Pedro Jose
相关产品推荐
相关产品推荐

