缩放和平移后fabricJS中的对象对齐

Posted

技术标签:

【中文标题】缩放和平移后fabricJS中的对象对齐【英文标题】:Object alignment in fabricJS after zoom and pan 【发布时间】:2021-06-18 07:58:41 【问题描述】:

当我想将元素左对齐时,我使用fabricJSAngular,例如我使用以下方法

alignLeft() 
    // Get Selected Elements
    var obj = this.canvas.getActiveObject();

    // if no element is selected
    if (obj !== undefined) 
      // Bounding Box of the selected element
      var bound = obj.getBoundingRect();

      obj.set('left', (obj.left - bound.left));
      //this.canvas.getActiveObject().setCoords();
      this.canvas.renderAll();
    

只有当我更改缩放比例或平移画布时,对齐才会像魅力一样发挥作用,如果我更改缩放比例或平移画布,一切都会以错误的方式进行。下面是我用于放大/缩小的方法

this.canvas.on('mouse:wheel', function (opt) 
  var delta = opt.e.deltaY;
  var zoom = this.canvas.getZoom();

  zoom *= 0.999 ** delta;
  if (zoom > 20) zoom = 20;
  if (zoom < 0.01) zoom = 0.01;
  this.canvas.zoomToPoint( x: opt.e.offsetX, y: opt.e.offsetY , zoom.toFixed(4));
  opt.e.preventDefault();
  opt.e.stopPropagation();
.bind(this));

this.canvas.on('mouse:down', function (opt) 
  var evt = opt.e;
  if (evt.altKey === true) 
    this.isDragging = true;
    this.selection = false;
    this.lastPosX = evt.clientX;
    this.lastPosY = evt.clientY;
  
);

this.canvas.on('mouse:move', function (opt) 
  if (this.isDragging) 
    var e = opt.e;
    var vpt = this.viewportTransform;
    vpt[4] += e.clientX - this.lastPosX;
    vpt[5] += e.clientY - this.lastPosY;
    this.requestRenderAll();
    this.lastPosX = e.clientX;
    this.lastPosY = e.clientY;
  
);

this.canvas.on('mouse:up', function (opt) 
  // on mouse up we want to recalculate new interaction
  // for all objects, so we call setViewportTransform
  this.setViewportTransform(this.viewportTransform);
  this.isDragging = false;
  this.selection = true;
);

在阅读了multiple questions 和fabricJS Documentation 之后,我将alignLeft() 方法更改为以下内容:

alignLeft() 
    // Get Selected Elements
    var obj = this.canvas.getActiveObject();

    // if no element is selected
    if (obj !== undefined) 
      // Bounding Box of the selected element
      var bound = obj.getBoundingRect();
      let p = x: (obj.width / 2), y: obj.top
      var invertedMatrix = fabric.util.invertTransform(this.canvas.viewportTransform);
      let newp = fabric.util.transformPoint(p, invertedMatrix);

      obj.set('left', newp.x);
      //this.canvas.getActiveObject().setCoords();
      this.canvas.renderAll();
    

【问题讨论】:

【参考方案1】:

您需要使用ViewPortCoordinates(参见fabricJS Docs)根据视口获取canvastop lefttop rightbottom leftbottom right 坐标。

描述设计属性上的画布元素扩展是 tl,tr,bl,br。如果画布没有缩放/平移这些点是画布的四个角如果画布是 viewportTransformed 你这些点表示画布元素在普通未变换坐标中的扩展坐标使用@method calcViewportBoundaries 更新。

对于alignLeft() 方法,您可以将其更新为以下内容:

alignLeft() 
    // Get Selected Elements
    var obj = this.canvas.getActiveObject();

    // if no element is selected
    if (obj !== undefined) 
        const viwePortCoords = this.canvas.vptCoords;
        obj.set('left', viwePortCoords.bl.x + (obj.width / 2));

        this.canvas.renderAll();
    
    this.canvas.fire('object:modified',  target: obj );

【讨论】:

以上是关于缩放和平移后fabricJS中的对象对齐的主要内容,如果未能解决你的问题,请参考以下文章

fabricjs:缩放后如何显示对象大小

如何通过平移、旋转和/或缩放调整来匹配两个分割蒙版

如何在平移/旋转后重新计算轴对齐的边界框

平移和缩放的替代方案

D3平移和缩放后的点击坐标(D3 click coordinates after pan and zoom)

UIScrollview 子视图在缩放后无法识别平移手势