在fabricJS中如何使用transformMatrix变换点?

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

我正在尝试将点(通过

fabric.Circle
制作)放置在
fabric.Polygon
的角上。用户可以移动、缩放或旋转多边形。但是,每次修改后我都希望获得多边形的新坐标来将我的圆放置在那里。

在深入研究这个主题时,我发现this对变换矩阵有很好的解释。我认为这是实现我想要实现的目标的完美解决方案。但正如你在小提琴中看到的,我的点总是远离我的多边形。

由于我对几何变换等不坚定。我希望有人能找到我的错误并告诉我我错过了什么:)谢谢。

var canvas = new fabric.Canvas("c", {selection: false});

var polygon = new fabric.Polygon([
  new fabric.Point(200, 50),
  new fabric.Point(250, 150),
  new fabric.Point(150, 150)
]);

polygon.on("modified", function () {
  var matrix = this.calcTransformMatrix();
  var transformedPoints = this.get("points").map(function(p){
    return fabric.util.transformPoint(p, matrix);
  });
  var circles = transformedPoints.map(function(p){
    return new fabric.Circle({
      left: p.x,
      top: p.y,
      radius: 3,
      fill: "red",
      originX: "center",
      originY: "center",
      hasControls: false,
      hasBorders: false,
      selectable: false
    });
  });
  
  this.canvas.clear().add(this).add.apply(this.canvas, circles).setActiveObject(this).renderAll();
});

canvas.add(polygon).renderAll();
canvas {
  border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
<p>
Move, scale and rotate the polygon. The three red dots should match with the corners of the polygon after each modification.
</p>
<canvas id="c" width="600" height="400"></canvas>


SO 相关问题:

javascript transform fabricjs transformation
4个回答
19
投票

这并不是一个真正的几何问题。 几何部分已经被你解决了。如果您查看 Fabricjs 的内部多边形类,您会注意到多边形作为 calcDimension 函数,其中每个点都有一个偏移量: http://fabricjs.com/docs/fabric.Polygon.html

要计算画布位置,您必须在转换之前添加该偏移量。

var canvas = new fabric.Canvas("c", {selection: false});

var polygon = new fabric.Polygon([
  new fabric.Point(200, 50),
  new fabric.Point(250, 150),
  new fabric.Point(150, 150)
]);

polygon.on("modified", function () {
  var matrix = this.calcTransformMatrix();
  var transformedPoints = this.get("points")
  .map(function(p){
    return new fabric.Point(p.x - polygon.minX -polygon.width/2, p.y - polygon.minY - polygon.height/2);
    })
  .map(function(p){
    return fabric.util.transformPoint(p, matrix);
  });
  var circles = transformedPoints.map(function(p){
    return new fabric.Circle({
      left: p.x,
      top: p.y,
      radius: 3,
      fill: "red",
      originX: "center",
      originY: "center",
      hasControls: false,
      hasBorders: false,
      selectable: false
    });
  });
  
  this.canvas.clear().add(this).add.apply(this.canvas, circles).setActiveObject(this).renderAll();
});

canvas.add(polygon).renderAll();
canvas {
  border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
<p>
Move, scale and rotate the polygon. The three red dots should match with the corners of the polygon after each modification.
</p>
<canvas id="c" width="600" height="400"></canvas>


14
投票

看起来上面提供的解决方案不适用于最新版本的fabricjs。我不确定,但在调查过程中,我读到从 2.0 版本开始他们改变了多边形的坐标。 2.0之前的点相对于多边形中心; 2.0之后它们对于画布来说是绝对的;

我对代码片段做了一些更改,它开始与 Fabricjs v2.4.3 一起使用

因此,它不仅适用于移动,而且适用于变换:例如调整大小、旋转、翻转

var canvas = new fabric.Canvas("c", {selection: false});

var polygon = new fabric.Polygon([
  new fabric.Point(200, 50),
  new fabric.Point(250, 150),
  new fabric.Point(150, 150)
]);

polygon.on("modified", function () {
  var matrix = this.calcTransformMatrix();
  var transformedPoints = this.get("points")
    .map(function(p){
      return new fabric.Point(
         p.x - polygon.pathOffset.x,
         p.y - polygon.pathOffset.y);
    })
  .map(function(p){
    return fabric.util.transformPoint(p, matrix);
  });
  var circles = transformedPoints.map(function(p){
    return new fabric.Circle({
      left: p.x,
      top: p.y,
      radius: 3,
      fill: "red",
      originX: "center",
      originY: "center",
      hasControls: false,
      hasBorders: false,
      selectable: false
    });
  });
  
  this.canvas.clear().add(this).add.apply(this.canvas, circles).setActiveObject(this).renderAll();
});

canvas.add(polygon).renderAll();
canvas {
  border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.js"></script>
<p>
Move, scale and rotate the polygon. The three red dots should match with the corners of the polygon after each modification.
</p>
<canvas id="c" width="600" height="400"></canvas>


0
投票

上面的代码可以正常工作并正确保存到数据库,但是当我放大和移动时,偏移量仍然存在于点中。 因此,我决定在设置点的同时设置宽度和高度。

var width = self.polygon.width;
var height = polygon.height;
var scaleX = polygon.scaleX;
var scaleY = polygon.scaleY;

polygon.set({
    width: width * scaleX,
    height: height * scaleY,
    scaleX: 1,
    scaleY: 1
});

0
投票

2024版本基于fabric 6.4.3和@VitaliiBratok答案:

polygon.on('modified', (o) => {
      const newCoords = polygon.get('points')
        .map(
          (p: Point) =>
            new Point(p.x - polygon.pathOffset.x, p.y - polygon.pathOffset.y),
        )
        .map((p: Point) => util.transformPoint(p, polygon.calcTransformMatrix()));

         polygon.set({'points': newCoords });
        // (...)
});
© www.soinside.com 2019 - 2024. All rights reserved.