javascript - Penjajaran objek di fabricJS setelah zoom dan pan


Saya menggunakan fabricJS dengan Angular ketika saya ingin menyelaraskan suatu elemen ke kiri, misalnya saya menggunakan metode berikut

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

Penyelarasan bekerja dengan sempurna hanya ketika zoom berada pada 100%, jika saya mengubah zoom atau menggeser kanvas, semuanya menjadi salah. Di bawah ini adalah metode yang saya gunakan untuk memperbesar/memperkecil.

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

Setelah saya membaca beberapa pertanyaan dan Dokumentasi fabricJS, saya mengubah metode alignLeft() menjadi berikut:

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

Jawaban #1

Anda perlu menggunakan ViewPortCoordinates (lihat Dokumentasi fabricJS) untuk mendapatkan koordinat top left, top right, bottom left, bottom right dari canvas sesuai dengan tampilan jendela pandang.

Jelaskan perluasan elemen kanvas terhadap properti desain adalah tl, tr, bl, br. Jika kanvas tidak diperbesar/digeser, titik-titik tersebut adalah empat sudut kanvas. Jika kanvas diubah dengan viewportTransformed, titik-titik tersebut menunjukkan perluasan elemen kanvas dalam koordinat polos yang tidak ditransformasikan. Koordinat diperbarui dengan @method calcViewportBoundaries.

untuk metode alignLeft() Anda dapat memperbaruinya menjadi berikut:

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

Artikel terkait