Recherche de site Web

javascript - Alignement des objets dans fabricJS après zoom et déplacement


J'utilise fabricJS avec Angular quand je veux aligner un élément à gauche par exemple j'utilise la méthode suivante

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

L'alignement fonctionne à merveille seulement lorsque le zoom est à 100 %, si je change le zoom ou que je déplace le canevas, tout se passe mal. Ci-dessous se trouvent les méthodes que j'utilise pour zoomer avant/arrière

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

Après avoir lu plusieurs questions et la documentation de fabricJS, j'ai modifié la méthode alignLeft() comme suit :

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

Réponse n°1

Vous devez utiliser ViewPortCoordinates (voir la documentation de fabricJS) pour obtenir les coordonnées en haut à gauche, en haut à droite, en bas à gauche, en bas à droite du canvas selon la fenêtre d'affichage.

Décrivez l'extension de l'élément canvas sur les propriétés de conception qui sont tl, tr, bl, br. Si le canvas n'est pas zoomé/déplacé, ces points sont les quatre coins du canvas. Si le canvas est transformé par la vue, ces points indiquent l'extension de l'élément canvas dans des coordonnées non transformées. Les coordonnées sont mises à jour avec la méthode @method calcViewportBoundaries.

pour la méthode alignLeft(), vous pouvez la mettre à jour comme suit :

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

Articles connexes