How does transforming points with a transformMatrix work in fabricJS?

让人想犯罪 __ 提交于 2019-11-26 14:25:43

问题


I'm trying to place points (made via fabric.Circle) on the corners of a fabric.Polygon. The polygon may be moved, scaled or rotated by the user. However, after each modification I want to have the new coordinates of the polygon to place my circles there.

While digging deeper into this topic I found this great explanation of transformation matrices. I thought it's the perfect solution for what I want to achieve. But as you can see in the Fiddle, my points are always way off my polygon.

As I'm not firm with geometric transformation etc. I hope someone can find my error and tell me what I'm missing :) Thanks.

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>

Related Questions on SO:

  • How to get polygon points in Fabric.js
  • Truly rotate center of equilateral triangle in Fabric.js
  • How do I transform a particular point which has been modified and update the points array of polygon?
  • FabricJs and Polygon transformed coordinates
  • How to multiply each point with object's transform matrix?
  • How do i get point coordinates after object modified?

回答1:


Not really a geometric problem. The geometric part was solve by you. If you would look at internal polygon class from fabricjs you would notice that polygon as a calcDimension function where every point gets an offset: http://fabricjs.com/docs/fabric.Polygon.html

To calculate canvas position you have to add that offset back before transforming.

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>



回答2:


It looks like the solution provided above doesn't work with the latest version of fabricjs. I'm not sure, but during the investigation, I've read that from version 2.0 they changed the coordinates of the polygon. Before 2.0 points relative to the center of the polygon; after 2.0 they are absolute to the canvas;

I made a few changes to the code snippet and it starts working with fabricjs v2.4.3

So, it works fine not only with moving but with transformations: such as resizing, rotation, flip

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>



回答3:


The above code was working and saving to database properly, but still the offset persisted in the points while I enlarged and moved. So, I decided to set the width and height along with setting the points.

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
});


来源:https://stackoverflow.com/questions/38999034/how-does-transforming-points-with-a-transformmatrix-work-in-fabricjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!