如何使用transformMatrix转换点在fabricJS中工作?

时间:2016-08-17 14:09:00

标签: javascript transform fabricjs transformation

我正在尝试将点(通过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的相关问题:

3 个答案:

答案 0 :(得分:10)

不是几何问题。 几何部分由你解决。如果您从fabricjs查看内部多边形类,您会注意到多边形作为calcDimension函数,其中每个点都获得一个偏移量: http://fabricjs.com/docs/fabric.Polygon.html

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

&#13;
&#13;
canvas {
  border: 1px solid;
}
&#13;
<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>
&#13;
    $ids= array(1,2,3,5,7,8);
    $newkeys = array('hck','scr','lcss','ftbl','bsktbl','stbl');

    $keyValueArray = array();   

    foreach($ids as $key=>$id)
    {
        $keyValueArray[$id] =$newkeys[$key];
    }


    $inputArr = array(1,3,7,8)  ;
    $outputArr = array();

    foreach($inputArr as $id)
    {
        $outputArr[$keyValueArray[$id]] = $id;
    }
    echo "<pre>";
    print_r($outputArr);
    echo "</pre>";
&#13;
&#13;
&#13;

答案 1 :(得分:2)

上面提供的解决方案似乎不适用于最新版本的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>

答案 2 :(得分: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
});