简体   繁体   English

在放大结构js时维护对象大小

[英]Maintaining object size while zooming in fabric js

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. 因此,如果我有一个高度和宽度为20的对象(对象组),即使我放大它,它默认仍然应该是20像素。 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. 我也在画布上循环了所有对象,然后为它设置了scaleX和scaleY,但结果对我来说太迟了。

 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> 

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. 这不是fabricjs的内置功能,您必须通过继承或修改fabric.Object类的标准代码来解决它。

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 . 这发生在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. 因此,标记您不需要使用新属性ignoreZoom默认为false进行缩放的对象。

Modify the fabric.Object.prototype.transform in this way: 以这种方式修改fabric.Object.prototype.transform:

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). 1.获得比例 - (1 / zoomLevel)。 I set it to "1" by default. 我默认将它设置为“1”。

Loop all the group objects and set the "scaleX" and "scaleY" into this kind of calculation. 循环所有组对象并将“scaleX”和“scaleY”设置为此类计算。

objects.forEach(object => {
  object.scaleX = (scale || 1) * 2.5;
  object.scaleY = (scale || 1) * 2.5;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM