在放大织物js时保持对象大小
即使用户放大或缩小,是否有任何解决方案可以保持对象大小?我想在谷歌地图上实现类似的行为.因此,如果我有一个高度和宽度为 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>
相关文章