如何在不放大fabricjs的情况下显示另一个画布 [英] How to display another canvas without zoom in fabricjs

查看:77
本文介绍了如何在不放大fabricjs的情况下显示另一个画布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之,我正在开发一个项目,其中有两个画布:一个支持缩放和绘图的画布,另一个画布-第一个画布的副本,应该显示不缩放的一般视图。不幸的是,我不了解如何实现此功能,因为第二个画布还显示了缩放图片。请帮忙!
这是我所拥有的一个小例子:

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的情况下显示另一个画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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