问题描述
简而言之,我正在开发一个项目,其中有两个画布:一个支持缩放和绘图的画布,另一个画布-第一个画布的副本,应该显示不缩放的一般视图。不幸的是,我不了解如何实现此功能,因为第二个画布还显示了缩放图片。请帮忙!
这是我所拥有的一个小例子:
In short, I am developing a project in which there are two canvases: a canvas that supports zoom and drawing, a second canvas - a duplicate of the first canvas, which should display a general view without zoom. Unfortunately, I do not understand how to implement this, since the second canvas also displays a picture with a zoom. Please, help!Here is a small example of what I have:
var c1 = document.getElementById("scale");
var c2 = document.getElementById("static");
var canvas = this.__canvas = new fabric.Canvas(c1, {
isDrawingMode: true
});
var ctx1 = c1.getContext("2d");
var ctx2 = c2.getContext("2d");
function copy() {
var imgData = ctx1.getImageData(0, 0, 512, 512);
ctx2.putImageData(imgData, 0, 0);
}
fabric.Image.fromURL(
"https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg",
img => {
img.scaleToWidth(canvas.width);
canvas.setBackgroundImage(img);
canvas.requestRenderAll();
},
{
crossOrigin: "Annoymous"
}
);
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var pointer = canvas.getPointer(opt.e);
var zoom = canvas.getZoom();
zoom = zoom + delta/200;
if (zoom > 20) zoom = 20;
if (zoom < 0.01) zoom = 0.01;
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
});
setInterval(() => {
copy();
}, 10)
canvas {
border: 1px solid black;
}
#static {
position: relative;
top: -300px;
left: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.1/fabric.min.js"> </script>
This is interactive canvas
<canvas id="scale" width="300" height="300"></canvas>
<canvas id="static"width="300" height="300"></canvas>
推荐答案
没有完美的解决方案,因为fabricJS不支持在更多目标上进行渲染。
There is not a perfect solution because fabricJS does not support rendering on more targets.
这里有一个toCanvasElement方法可创建另一个画布的副本,
There is a toCanvasElement method here that creates a copy to another canvas, but it does not let you specify the canvas you want to draw on.
所以在某些时候,我正在做的事情是
So here what i m doing is, at some point:
- 将缩放比例重置为1
- 渲染到新画布
- 放回缩放比例是什么
- 在静态画布上复制该画布
- reset the zoom to 1
- render to a new canvas
- put back the zoom to what it was
- copy that canvas on the static canvas
还有一个额外的副本,在现代硬件上这是快速的,到您根本不在乎的程度,但是最好在该toCanvasElement方法中添加canvas参数,以使绘图发生在指定的画布上,
There is an extra copy, that is fast on modern hardware, to the point that you do not care, but would be nicer to add a canvas argument to that toCanvasElement method in order to get the drawing happening on the specified canvas immediately
然后除了触发该副本时还有一个问题。
'after:render'不是一个好主意,它会永远循环播放,并且还会在缩放更改时重新绘制,这不是您想要的。
Then apart from that there is the quesiton on when firing that copy.'after:render' is not a great idea, it will loop forever and it will also redraw on zoom changes, that is not what you want.
现在,我使用object:add,也可以添加object:modified,也许还有其他东西,但是理想情况下,当您运行某些会更改某些图形属性的代码时,可以在需要时手动调用副本。
For now i use object:added, you can add also object:modified, and maybe something else but ideally you will call a copy manually when needed when you run some code that will change some of the drawing properties.
var c1 = document.getElementById("scale");
var c2 = document.getElementById("static");
var canvas = this.__canvas = new fabric.Canvas(c1, {
isDrawingMode: true
});
var ctx2 = c2.getContext("2d");
function copy(copiedCanvas) {
ctx2.drawImage(copiedCanvas,0,0);
}
fabric.Image.fromURL(
"https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg",
img => {
img.scaleToWidth(canvas.width);
canvas.setBackgroundImage(img);
canvas.requestRenderAll();
},
{
crossOrigin: "Annoymous"
}
);
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var pointer = canvas.getPointer(opt.e);
var zoom = canvas.getZoom();
zoom = zoom + delta/200;
if (zoom > 20) zoom = 20;
if (zoom < 0.01) zoom = 0.01;
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
});
function afterRender() {
var originalVP = canvas.viewportTransform;
canvas.viewportTransform = [1, 0, 0, 1, 0, 0];
copy(canvas.toCanvasElement());
canvas.viewportTransform = originalVP;
}
canvas.on('object:added', afterRender);
canvas.on('object:modified', afterRender);
canvas {
border: 1px solid black;
}
#static {
position: relative;
top: -300px;
left: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.1/fabric.min.js"> </script>
This is interactive canvas
<canvas id="scale" width="300" height="300"></canvas>
<canvas id="static"width="300" height="300"></canvas>
这篇关于如何在不放大fabricjs的情况下显示另一个画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!