Fabricjs canvas 缩放后重置
Fabricjs canvas reset after zooming
我有一个 fabricjs canvas,我需要能够放大和缩小并多次更改内部的 image/object。
为此,我在第一次加载页面时设置了 canvas,如下所示:
fabric.Object.prototype.hasBorders = false;
fabric.Object.prototype.hasControls = false;
canvas = new fabric.Canvas('my_canvas', {renderOnAddRemove: false, stateful: false});
canvas.defaultCursor = "pointer";
canvas.backgroundImageStretch = false;
canvas.selection = false;
canvas.clear();
var image = document.getElementById('my_image');
if (image != null) {
imageSrc = image.src;
if(imageSrc.length > 0){
fabric.Image.fromURL(imageSrc, function(img) {
img = scaleImage(canvas, img); //shrinks the image to fit the canvas
img.selectable = false;
canvas.centerObject(img);
canvas.setActiveObject(img);
canvas.add(img);
});
}
}
canvas.deactivateAll().renderAll();
然后当我需要更改 canvas 中的 image/object 或当页面重新加载时,我尝试像这样重置 canvas:
canvas.clear();
canvas.remove(canvas.getActiveObject());
var image = document.getElementById('my_image');
if (image != null) {
imageSrc = image.src;
if(imageSrc.length > 0){
fabric.Image.fromURL(imageSrc, function(img) {
img = scaleImage(canvas, img); //shrinks the image to fit the canvas
img.selectable = false;
canvas.centerObject(img);
canvas.setActiveObject(img);
canvas.add(img);
});
}
}
不确定这是否重要,但我更改图像的方式是通过更改 'my_image' 中的源并使用上述方法重置 canvas。
在我使用 canvas.zoomToPoint
之前效果很好,根据 this 线程,在此之后,当我重置缩放或单击 canvas 时,image/object 开始改变位置] 在缩放时用鼠标,似乎在左上角方向的每个变化处跳跃,最终从视图中消失。
重置缩放:
canvas.setZoom(1);
resetCanvas(); //(above method)
如何恢复 image/object 位置?
我尝试进行初始设置而不是重置,并尝试在视觉上工作,但实际上在每个新设置中都添加了一个新的上层 canvas,所以这并不好。
有没有办法将 canvas 重置为原始状态而不会导致此行为并且仍然能够正确缩放 in/out?
请参阅下面的代码片段 - 我在这里做同样的事情 - 一起缩放,但取消组合对象以防有人点击它。
获取原始对象属性的问题可以解决,取消分组并创建它们的副本并重新附加 - 有点烦人,但这是我找到的唯一解决方案。
<script id="main">
// canvas and office background
var mainGroup;
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
createOnjects(canvas);
// events - zoom
$(canvas.wrapperEl).on('mousewheel', function(e) {
var target = canvas.findTarget(e);
var delta = e.originalEvent.wheelDelta / 5000;
if (target) {
target.scaleX += delta;
target.scaleY += delta;
// constrain
if (target.scaleX < 0.1) {
target.scaleX = 0.1;
target.scaleY = 0.1;
}
// constrain
if (target.scaleX > 10) {
target.scaleX = 10;
target.scaleY = 10;
}
target.setCoords();
canvas.renderAll();
return false;
}
});
// mouse down
canvas.on('mouse:up', function(options) {
if (options.target) {
var thisTarget = options.target;
var mousePos = canvas.getPointer(options.e);
if (thisTarget.isType('group')) {
// unGroup
console.log(mousePos);
var clone = thisTarget._objects.slice(0);
thisTarget._restoreObjectsState();
for (var i = 0; i < thisTarget._objects.length; i++) {
var o = thisTarget._objects[i];
if (o._element.alt == "officeFloor")
continue;
else {
if (mousePos.x >= o.originalLeft - o.currentWidth / 2 && mousePos.x <= o.originalLeft + o.currentWidth / 2
&& mousePos.y >= o.originalTop - o.currentHeight / 2 && mousePos.y <= o.originalTop + o.currentHeight / 2)
console.log(o._element.alt);
}
}
// remove all objects and re-render
canvas.remove(thisTarget);
canvas.clear().renderAll();
var group = new fabric.Group();
for (var i = 0; i < clone.length; i++) {
group.addWithUpdate(clone[i]);
}
canvas.add(group);
canvas.renderAll();
}
}
});
// functions
function createOnjects(canvas) {
// ToDo: jQuery.parseJSON() for config file (or web service)
fabric.Image.fromURL('pics/OfficeFloor.jpg', function(img) {
var back = img.set({ left: 100, top: 100 });
back._element.alt = "officeFloor";
back.hasControls = false;
fabric.Image.fromURL('pics/me.png', function(img) {
var me = img.set({ left: -420, top: 275 });
me._element.alt = "me";
console.log(me);
var group = new fabric.Group([ back, me], { left: 700, top: 400, hasControls: false });
canvas.clear().renderAll();
canvas.add(group);
// remove all objects and re-render
});
});
}
</script>
我最终解决了我遇到的问题。
要重置缩放,而不是仅使用 canvas.setZoom(1)
将缩放设置为 1,我将 canvas.zoomToPoint
方法重新应用到同一点但使用缩放 1,以强制初始缩放但关于用于放大的相同点。
至于在 canvas 中恢复图像位置的问题(例如在平移之后),就像删除图像一样简单,将其置于 canvas 的中心并重新添加到canvas 与第一次添加时一样:
var img = canvas.getActiveObject();
canvas.remove(img);
canvas.centerObject(img);
canvas.setActiveObject(img);
canvas.add(img);
canvas.renderAll();
虽然这个问题很老,但这是我使用 fabric.js 2.2.4 的当前版本所做的:
canvas.setViewportTransform([1,0,0,1,0,0]);
供您参考:缩放到一个点是对视口变换的重新计算。上面的矩阵是初始视口变换矩阵。
我有一个 fabricjs canvas,我需要能够放大和缩小并多次更改内部的 image/object。
为此,我在第一次加载页面时设置了 canvas,如下所示:
fabric.Object.prototype.hasBorders = false;
fabric.Object.prototype.hasControls = false;
canvas = new fabric.Canvas('my_canvas', {renderOnAddRemove: false, stateful: false});
canvas.defaultCursor = "pointer";
canvas.backgroundImageStretch = false;
canvas.selection = false;
canvas.clear();
var image = document.getElementById('my_image');
if (image != null) {
imageSrc = image.src;
if(imageSrc.length > 0){
fabric.Image.fromURL(imageSrc, function(img) {
img = scaleImage(canvas, img); //shrinks the image to fit the canvas
img.selectable = false;
canvas.centerObject(img);
canvas.setActiveObject(img);
canvas.add(img);
});
}
}
canvas.deactivateAll().renderAll();
然后当我需要更改 canvas 中的 image/object 或当页面重新加载时,我尝试像这样重置 canvas:
canvas.clear();
canvas.remove(canvas.getActiveObject());
var image = document.getElementById('my_image');
if (image != null) {
imageSrc = image.src;
if(imageSrc.length > 0){
fabric.Image.fromURL(imageSrc, function(img) {
img = scaleImage(canvas, img); //shrinks the image to fit the canvas
img.selectable = false;
canvas.centerObject(img);
canvas.setActiveObject(img);
canvas.add(img);
});
}
}
不确定这是否重要,但我更改图像的方式是通过更改 'my_image' 中的源并使用上述方法重置 canvas。
在我使用 canvas.zoomToPoint
之前效果很好,根据 this 线程,在此之后,当我重置缩放或单击 canvas 时,image/object 开始改变位置] 在缩放时用鼠标,似乎在左上角方向的每个变化处跳跃,最终从视图中消失。
重置缩放:
canvas.setZoom(1);
resetCanvas(); //(above method)
如何恢复 image/object 位置?
我尝试进行初始设置而不是重置,并尝试在视觉上工作,但实际上在每个新设置中都添加了一个新的上层 canvas,所以这并不好。
有没有办法将 canvas 重置为原始状态而不会导致此行为并且仍然能够正确缩放 in/out?
请参阅下面的代码片段 - 我在这里做同样的事情 - 一起缩放,但取消组合对象以防有人点击它。
获取原始对象属性的问题可以解决,取消分组并创建它们的副本并重新附加 - 有点烦人,但这是我找到的唯一解决方案。
<script id="main">
// canvas and office background
var mainGroup;
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
createOnjects(canvas);
// events - zoom
$(canvas.wrapperEl).on('mousewheel', function(e) {
var target = canvas.findTarget(e);
var delta = e.originalEvent.wheelDelta / 5000;
if (target) {
target.scaleX += delta;
target.scaleY += delta;
// constrain
if (target.scaleX < 0.1) {
target.scaleX = 0.1;
target.scaleY = 0.1;
}
// constrain
if (target.scaleX > 10) {
target.scaleX = 10;
target.scaleY = 10;
}
target.setCoords();
canvas.renderAll();
return false;
}
});
// mouse down
canvas.on('mouse:up', function(options) {
if (options.target) {
var thisTarget = options.target;
var mousePos = canvas.getPointer(options.e);
if (thisTarget.isType('group')) {
// unGroup
console.log(mousePos);
var clone = thisTarget._objects.slice(0);
thisTarget._restoreObjectsState();
for (var i = 0; i < thisTarget._objects.length; i++) {
var o = thisTarget._objects[i];
if (o._element.alt == "officeFloor")
continue;
else {
if (mousePos.x >= o.originalLeft - o.currentWidth / 2 && mousePos.x <= o.originalLeft + o.currentWidth / 2
&& mousePos.y >= o.originalTop - o.currentHeight / 2 && mousePos.y <= o.originalTop + o.currentHeight / 2)
console.log(o._element.alt);
}
}
// remove all objects and re-render
canvas.remove(thisTarget);
canvas.clear().renderAll();
var group = new fabric.Group();
for (var i = 0; i < clone.length; i++) {
group.addWithUpdate(clone[i]);
}
canvas.add(group);
canvas.renderAll();
}
}
});
// functions
function createOnjects(canvas) {
// ToDo: jQuery.parseJSON() for config file (or web service)
fabric.Image.fromURL('pics/OfficeFloor.jpg', function(img) {
var back = img.set({ left: 100, top: 100 });
back._element.alt = "officeFloor";
back.hasControls = false;
fabric.Image.fromURL('pics/me.png', function(img) {
var me = img.set({ left: -420, top: 275 });
me._element.alt = "me";
console.log(me);
var group = new fabric.Group([ back, me], { left: 700, top: 400, hasControls: false });
canvas.clear().renderAll();
canvas.add(group);
// remove all objects and re-render
});
});
}
</script>
我最终解决了我遇到的问题。
要重置缩放,而不是仅使用 canvas.setZoom(1)
将缩放设置为 1,我将 canvas.zoomToPoint
方法重新应用到同一点但使用缩放 1,以强制初始缩放但关于用于放大的相同点。
至于在 canvas 中恢复图像位置的问题(例如在平移之后),就像删除图像一样简单,将其置于 canvas 的中心并重新添加到canvas 与第一次添加时一样:
var img = canvas.getActiveObject();
canvas.remove(img);
canvas.centerObject(img);
canvas.setActiveObject(img);
canvas.add(img);
canvas.renderAll();
虽然这个问题很老,但这是我使用 fabric.js 2.2.4 的当前版本所做的:
canvas.setViewportTransform([1,0,0,1,0,0]);
供您参考:缩放到一个点是对视口变换的重新计算。上面的矩阵是初始视口变换矩阵。