最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Maintaining object size while zooming in fabric js - Stack Overflow

programmeradmin1浏览0评论

Is there any solution for maintaining object size even if the user zoom in or out? I want to achieve like on the google maps behavior. So if I have an object (group of object) with a height and width of 20 even if I zoom into it, it should still be 20 pixels by default. Right now the behavior I have is that when the user zoom in or out the image gets bigger / smaller. I also did looping all the objects that I have on the canvas then set the scaleX and scaleY for it but the result was so laggy for me.

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

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


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=".1.1/jquery.min.js"></script>
<script src=".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>

Is there any solution for maintaining object size even if the user zoom in or out? I want to achieve like on the google maps behavior. So if I have an object (group of object) with a height and width of 20 even if I zoom into it, it should still be 20 pixels by default. Right now the behavior I have is that when the user zoom in or out the image gets bigger / smaller. I also did looping all the objects that I have on the canvas then set the scaleX and scaleY for it but the result was so laggy for me.

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

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


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./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare./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>

Share Improve this question edited Feb 2, 2018 at 9:18 AndreaBogazzi 14.8k3 gold badges41 silver badges67 bronze badges asked Feb 2, 2018 at 8:52 Mark SantosMark Santos 3771 gold badge3 silver badges15 bronze badges 10
  • If you want to maintain the scale of the objects then what is the use of canvas zoom? – Durga Commented Feb 2, 2018 at 9:20
  • I did some work around on it using the zoom level divided by 1 but the output for me was so laggy. – Mark Santos Commented Feb 2, 2018 at 9:24
  • I already updated the fiddle example. Right now I'm experiencing so much lag when zoom in or out since the group are posed of 6 different type of objects. – Mark Santos Commented Feb 2, 2018 at 9:28
  • 1 The right example for my problem is the google maps. I want the object not to get bigger or smaller even if I zoom in or out into it. – Mark Santos Commented Feb 2, 2018 at 9:32
  • Mark the lag can e from the fabric 1.5 version. Depending how much code you wrote and on what project you are, try to switch to 2.0 or at least 1.7.22 How many groups of 6 objects do you have on your map? – AndreaBogazzi Commented Feb 2, 2018 at 9:33
 |  Show 5 more ments

2 Answers 2

Reset to default 4

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./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare./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;
});
发布评论

评论列表(0)

  1. 暂无评论