Maintaining object size while zooming in fabric js

五迷三道 提交于 2019-12-06 02:02:49

This is not a built in feature of fabricjs and you have to solve it with subclassing or modification of the standard code of the fabric.Object class.

I will make an example then you can use it to find the solution that better suits your project.

So for the whole canvas there is a zoom stage, and then every object has its own transformation. This happen in fabric.Object.prototype.transform. At that point the zoom is done and you can't really avoid it. What you can do is zoom in the opposite direction before drawing.

So flag the objects you need to do not zoom with a new property ignoreZoom default to false.

Modify the fabric.Object.prototype.transform in this way:

transform: function(ctx, fromLeft) {
      if (this.group && !this.group._transformDone && this.group === this.canvas._activeGroup) {
        this.group.transform(ctx);
      }
      // ADDED CODE FOR THE ANSWER
      if (this.ignoreZoom && !this.group && this.canvas) {
        var zoom = 1 / this.canvas.getZoom();
        ctx.scale(zoom, zoom);
      }
      // END OF ADDED CODE FOR THE ANSWER
      var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();
      ctx.translate(center.x, center.y);
      this.angle && ctx.rotate(degreesToRadians(this.angle));
      ctx.scale(
        this.scaleX * (this.flipX ? -1 : 1),
        this.scaleY * (this.flipY ? -1 : 1)
      );
      this.skewX && ctx.transform(1, 0, Math.tan(degreesToRadians(this.skewX)), 1, 0, 0);
      this.skewY && ctx.transform(1, Math.tan(degreesToRadians(this.skewY)), 0, 1, 0, 0);
    },

This solves rendering, but does not solve controls and caching. Caching is harder to understand, so i suggest you just disable caching for the objects that do not need to zoom.

For controls i ll be back later, is not super simple.

fabric.Object.prototype.ignoreZoom = false;
fabric.Object.prototype.transform = function(ctx, fromLeft) {
          if (this.group && !this.group._transformDone && this.group === this.canvas._activeGroup) {
            this.group.transform(ctx);
          }
          // ADDED CODE FOR THE ANSWER
          if (this.ignoreZoom && !this.group && this.canvas) {
            var zoom = 1 / this.canvas.getZoom();
            ctx.scale(zoom, zoom);
          }
          // END OF ADDED CODE FOR THE ANSWER
          var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();
          ctx.translate(center.x, center.y);
          this.angle && ctx.rotate(degreesToRadians(this.angle));
          ctx.scale(
            this.scaleX * (this.flipX ? -1 : 1),
            this.scaleY * (this.flipY ? -1 : 1)
          );
          this.skewX && ctx.transform(1, 0, Math.tan(degreesToRadians(this.skewX)), 1, 0, 0);
          this.skewY && ctx.transform(1, Math.tan(degreesToRadians(this.skewY)), 0, 1, 0, 0);
        };

var canvas = new fabric.Canvas('c') ;

var circle = new fabric.Circle({
  radius: 20, fill: 'red', left: 100, top: 100, ignoreZoom: true
});


var triangle = new fabric.Triangle({
   fill: 'red', left: 200, top: 200
});
canvas.add(circle, triangle) ;
//canvas.zoomToPoint(new fabric.Point(canvas.getCenter().left, canvas.getCenter().top,1)) ;

$(function(){
   
    $('#zoomIn').click(function(){
        canvas.setZoom(canvas.getZoom() * 1.1 ) ;
    }) ;
    
    $('#zoomOut').click(function(){
        canvas.setZoom(canvas.getZoom() / 1.1 ) ;
    }) ;
    
}) ;
#canvasContainer {border: dotted gray thin ;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"></script>
<button id="zoomIn">+</button>
<button id="zoomOut">-</button>
<div id="canvasContainer">
    <canvas id="c" width="400" height="400"></canvas>
</div>

Here are the following steps on how we solved this problem:

1.GET the scale - (1 / zoomLevel). I set it to "1" by default.

Loop all the group objects and set the "scaleX" and "scaleY" into this kind of calculation.

objects.forEach(object => {
  object.scaleX = (scale || 1) * 2.5;
  object.scaleY = (scale || 1) * 2.5;
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!