How does transforming points with a transformMatrix work in fabricJS?

后端 未结 3 1977
耶瑟儿~
耶瑟儿~ 2020-12-01 17:54

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. H

相关标签:
3条回答
  • 2020-12-01 18:15

    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
    });
    
    0 讨论(0)
  • 2020-12-01 18:17

    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>

    0 讨论(0)
  • 2020-12-01 18:20

    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>

    0 讨论(0)
提交回复
热议问题