放大Fabric JS时保持对象大小 [英] Maintaining object size while zooming in fabric js

查看:123
本文介绍了放大Fabric JS时保持对象大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使用户放大或缩小,是否有任何解决方案来保持对象大小?我想实现类似Google Maps的行为.因此,即使我放大了一个对象(一组对象),其高度和宽度均为20,默认情况下它仍应为20像素.现在,我的行为是当用户放大或缩小图像时,图像会变大或变小.我也确实循环了画布上所有的对象,然后为其设置了scaleX和scaleY,但结果对我来说太迟了.

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.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>

推荐答案

这不是fabricjs的内置功能,您必须通过子类化或修改fabric.Object类的标准代码来解决它.

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.

因此,对于整个画布,都有一个缩放阶段,然后每个对象都有其自己的变换.这发生在fabric.Object.prototype.transform中.到那时,缩放已完成,您无法避免.您可以做的是在绘制之前朝相反的方向缩放.

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.

因此使用新属性ignoreZoom标记不需要缩放的对象,默认为false.

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

以这种方式修改fabric.Object.prototype.transform:

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>

这篇关于放大Fabric JS时保持对象大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆