javascript - 渲染前保存canvas的dataImage

标签 javascript html5-canvas fabricjs

我正在开发一个项目,其中有两个 Canvas 。第一个 Canvas 支持缩放和绘图,第二个 Canvas 是第一个 Canvas 的副本,它应该显示第一个 Canvas 的一般 View ,无需缩放。我已经问过这个here ,这就是我 have现在。在此解决方案中,我在缩放之前使用函数 toDataURL 复制 Canvas 的状态。但这是一种非常慢的方法,而且性能很差。我尝试使用 getImageData 代替, got not what I expected 。我还尝试使用函数 after:renderbefore:render,但没有结果,请查看 this 。我做错了什么?

最佳答案

1) Fabric.js 会放大其 Canvas ,如果 devicePixelRatio is > 1。这就是为什么当您绘制从 getImageData() 获得的像素时会得到“缩放”图片的原因。更好的方法是使用 drawImage() 并为其提供目标宽度/高度,以便浏览器决定是否应根据源图像尺寸缩小或放大这些像素。

2)您关于重置视口(viewport)变换的说法是正确的,但这还不够 - 您应该应用这个新的变换并以某种方式重新渲染 Canvas 。这就是 Fabric.js 在调用 toDataURL() 时所做的事情 - 它调用 toCanvasElement(),这会创建 Canvas 的副本并在其上渲染所有对象。您的实现应该反射(reflect)此逻辑。

下面的解决方案引入了 drawOnCopyCanvas() 方法,它是 toCanvasElement() 的修补版本。它不使用中间 Canvas ,而是直接在提供的 Canvas 上绘制。

fabric.StaticCanvas.prototype.drawCopyOnCanvas = function(canvasEl) {
  // save values
  var scaledWidth = this.width,
      scaledHeight = this.height,
      vp = this.viewportTransform,
      originalInteractive = this.interactive,
      newVp = [1, 0, 0, 1, 0, 0],
      originalRetina = this.enableRetinaScaling,
      originalContextTop = this.contextTop;
  // reset
  this.contextTop = null;
  this.enableRetinaScaling = false;
  this.interactive = false;
  this.viewportTransform = newVp;
  this.calcViewportBoundaries();
  // draw on copy
  this.renderCanvas(canvasEl.getContext('2d'), this._objects);
  // restore values
  this.viewportTransform = vp;
  this.calcViewportBoundaries();
  this.interactive = originalInteractive;
  this.enableRetinaScaling = originalRetina;
  this.contextTop = originalContextTop;
}

function afterRender() {
  // remove 'after:render' listener as canvas.toCanvasElement()
  // calls renderCanvas(), which results in an infinite recursion
  canvas.off('after:render', afterRender);
  // draw c1 contents on c2
  canvas.drawCopyOnCanvas(c2);
  setTimeout(() => {
    // re-attach the listener in the next event loop
    canvas.on('after:render', afterRender);
  });
}

canvas.on('after:render', afterRender);

关于javascript - 渲染前保存canvas的dataImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60151384/

相关文章:

javascript - 定期更新 HTML 元素显示的文本并在内容数组结束时停止

javascript - 带 Canvas 的 2 列网格

javascript - 无法在 Edge 浏览器上将 Canvas 另存为图像

javascript - 在覆盖图像下绘制新路径

javascript - data-api 中的 Bootgrid ajax 设置

javascript - 编写自己的代码后,Angularjs 无法在 Windows chrome 和 firefox 中工作

javascript - 二维多边形边中的矩形镶嵌不重叠

javascript - 无法在 'putImageData' : parameter 1 is not of type 'CanvasRenderingContext2D' 上执行 'ImageData'

javascript - 如何按组获取对象的 Angular 、坐标和比例?

javascript - 在 jQuery 中格式化数字的简单方法