fabric.js 在移动点后重置多边形边界框

问题描述 投票:0回答:1

当我用鼠标移动多边形的点(节点)时,边界框不会更新以包含所有新点。我已经尝试了该网站上的每个矩阵、setCoords() 等好几天了。 Fabric 自己的演示没有用,因为它在翻转多边形时失败(3 年多了,没有修复)。我只想通过移动节点(点)和/或移动多边形位置来编辑多边形,而无需一千行代码。示例中未实现旋转和调整大小(不知道如何实现)。

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/fabric@latest/dist/fabric.js"></script>
<script>
$(document).ready(function() {
  var canvas,circles,points,polygon,shape,matrix,nodeNum=0;
  var mouse,orgLeft=0,orgTop=0,nodeX,nodeY;
  
  canvas = new fabric.Canvas($('canvas')[0],{ objectCaching:false,
                   preserveObjectStacking:true,perPixelTargetFind:true });
  points = [{"x":60,"y":40},{"x":100,"y":60},{"x":100,"y":100},{"x":60,"y":120},{"x":20,"y":100},{"x":20,"y":60}]
  
  polygon = new fabric.Polygon(points,{selectable:true,objectCaching:false});
  canvas.add(polygon); shape = polygon; 
  orgLeft = shape.left; orgTop = shape.top;
  addNodes(shape);
  
canvas.on('mouse:move', function(e){
  mouse = canvas.getPointer(e);
  $('#debug').text('x:'+parseInt(mouse.x)+' y:'+parseInt(mouse.y)
  +' shapeCenter:'+parseInt(polygon.getCenterPoint().x));
});

canvas.on('object:moving', function (e) {
  if (e.target.get('type')=='circle') {
    var node = e.target;
    nodeX = node.getCenterPoint().x; nodeY = node.getCenterPoint().y
    polygon.points[node.nodeNum] = {x:nodeX-(polygon.left-orgLeft), y:nodeY-(polygon.top-orgTop)};
    //node.setCoords();
    polygon.setCoords();
  }
});

shape.on('mousedown', function(e) {
  nodes.forEach((node, i) => { canvas.remove(node); });
});

shape.on('modified', function () {
  addNodes(this);
});

canvas.on('mouse:up', function(e) {
  if (e.target && e.target.get('type')=='circle') {
  var node = e.target;
  //const { width, height, left, top } = polygon._calcDimensions();
  //polygon.set({width,height,
      //pathOffset: new fabric.Point(left + width / 2, top + height / 2),
  //}).setCoords();
  }
});

function addNodes(shape) {
  matrix = shape.calcTransformMatrix(); nodeNum=0;
  var transformedPoints = shape.get("points").map(function(p){
    return new fabric.Point( p.x - shape.pathOffset.x, p.y - shape.pathOffset.y);
    }).map(function(p){
      return fabric.util.transformPoint(p, matrix);
  });
  
  nodes = transformedPoints.map(function(p){
    return new fabric.Circle({nodeNum:nodeNum++,shape:'node',left:p.x,top:p.y,radius:9,fill:"red",originX:"center",originY:"center",hoverCursor:'pointer',objectCaching:false,hasControls:false,hasBorders:false,selectable:true,opacity:.5});
  });
 canvas.clear().add(shape).add.apply(canvas,nodes).renderAll(); 
};

}); //end ready
</script>
</head>

<body>
  <canvas id="canvas" class="" width="640" height="512" style="border:1px solid black"></canvas>
  <div id="debug" style="width: 640px; padding: 5px 0 0 5px;">debug:</div>
</body>
</html>

示例:示例在这里

polygon edit point fabric bounding
1个回答
0
投票

经过几周尝试通过 Fabric 的 Matrix 完成此操作后,我放弃了并决定在每次修改时重新绘制多边形。当移动、缩放、旋转、调整大小或通过鼠标移动点时,它可以完美地工作。也许 Fabric 团队可以重新设计他们的演示(翻转时不起作用)并使用我的方法?

JSfiddle:这是如何以简单的方式做到这一点

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Fabric.js Polygon move,flip,scale,resize,rotate by Robert W. Stewart</title>
<script type="text/javascript" src="../../js/jquery-3.1.0.min.js"></script>
<script type="text/javascript" src="../../js/fabric.min.js"></script>
<script>
$(document).ready(function() {
  var canvas,circles,points,polygon,shape,matrix,nodeNum=0;
  var mouse,orgLeft=0,orgTop=0,nodeX,nodeY;
  canvas = new fabric.Canvas($('canvas')[0],{ objectCaching:false,preserveObjectStacking:true,perPixelTargetFind:true });

canvas.on('mouse:move', function(e){
  mouse = canvas.getPointer(e);
  $('#debug').text('x:'+parseInt(mouse.x)+' y:'+parseInt(mouse.y));
});

canvas.on('object:moving', function (e) {
  if (e.target.get('type')=='circle') {
    var node = e.target;
    nodeX = node.getCenterPoint().x; nodeY = node.getCenterPoint().y
    shape.points[node.nodeNum] = {x:nodeX-(shape.left-orgLeft), y:nodeY-(shape.top-orgTop)};
  }
});

canvas.on('mouse:up', function(e) {
  if (e.target && e.target.get('type')=='circle') {
    var node = e.target;
    resetPoints();
  } //end circle
});//mouseup

points = [{"x":60,"y":40},{"x":100,"y":60},{"x":100,"y":100},{"x":60,"y":120},{"x":20,"y":100},{"x":20,"y":60}]
makePolygon();

function resetPoints() {
  points.forEach((point, i) => { points[i]={x:nodes[i].left,y:nodes[i].top}; });
  makePolygon(); 
}

function makePolygon(e) {
  shape = new fabric.Polygon(points,{selectable:true,objectCaching:false});
  canvas.add(shape); 
  orgLeft = shape.left; orgTop = shape.top;
  addNodes(shape);
  shape.on('mousedown', function(e) {nodes.forEach((node, i) => { canvas.remove(node); })});
  shape.on('modified', function () { addNodes(this); resetPoints() });
}

function addNodes(shape) {
  matrix = shape.calcTransformMatrix(); nodeNum=0;
  var transformedPoints = shape.get("points").map(function(p){
    return new fabric.Point( p.x - shape.pathOffset.x, p.y - shape.pathOffset.y);
    }).map(function(p){
      return fabric.util.transformPoint(p, matrix);
  });
  
  nodes = transformedPoints.map(function(p){
    return new fabric.Circle({nodeNum:nodeNum++,shape:'node',left:p.x,top:p.y,radius:9,fill:"red",originX:"center",originY:"center",
    hoverCursor:'pointer',objectCaching:false,hasControls:false,hasBorders:false,selectable:true,opacity:.5});
  });
  canvas.clear().add(shape).add.apply(canvas,nodes).renderAll();
};

}); //end ready
</script>
</head>

<body>
  <canvas id="canvas" class="" width="640" height="512" style="border:1px solid black"></canvas>
  <div id="debug" style="width: 640px; padding: 5px 0 0 5px;">debug:</div>
</body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.