javascript - zoom ve pan sonrası fabricJS'de nesne hizalaması


Angular ile fabricJS kullanıyorum, örneğin bir öğeyi sola hizalamak istediğimde aşağıdaki yöntemi kullanıyorum

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

Hizalama, yalnızca yakınlaştırma %100 olduğunda sorunsuz çalışıyor; yakınlaştırmayı değiştirir veya tuvali kaydırırsam her şey yanlış yöne gidiyor. Aşağıda yakınlaştırma açma/kapatma için kullandığım yöntemler var

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

Birden fazla soru ve fabricJS Dokümantasyonunu okuduktan sonra alignLeft() metodunu şu şekilde değiştirdim:

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

Cevap #1

canvas için top left, top right, bottom left, bottom right koordinatlarını görünüm alanına göre almak için ViewPortCoordinates (bkz. fabricJS Dokümanları) kullanmanız gerekir.

Tuval öğesinin tasarım özellikleri üzerindeki uzantısını tl, tr, bl, br olarak tanımlayın. Eğer tuval yakınlaştırılmamış/taşınmamışsa, bu noktalar tuvalin dört köşesidir; eğer tuval viewportTransformed ise, bu noktalar tuval öğesinin düz, dönüştürülmemiş koordinatlardaki uzantısını gösterir. Koordinatlar @method calcViewportBoundaries ile güncellenir.

alignLeft() metodu için bunu aşağıdaki şekilde güncelleyebilirsiniz:

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

İlgili makaleler