克隆画布不起作用

时间:2018-03-17 06:59:51

标签: javascript canvas

我正在尝试克隆由https://github.com/Kaiido/SVG2Bitmap/blob/master/SVG2Bitmap.js绘制的canvas元素 图书馆,它不起作用。该库成功创建canvas元素并将其附加到html,但是当我尝试克隆它时,它只会添加空的canvas元素。这是我试图使用的代码:

let svg = d3.select("div#main svg").node();
let canvas = d3.select("#canvas0")
                    .append("canvas")
                    .attr("width", 500)
                    .attr("height", 500)
                    .node();
SVG2Bitmap(svg, canvas);
this.props.datum.map((clusterObj, idx) => {
  if (idx > 0) {
    let canvasId = "div#canvas" + idx;
    let clonedCanvas = this.canvasClone(canvas);
    d3.select(canvasId)
      .append(function() {
        return clonedCanvas;
      });
  }
})

显然,我选择了div标记d3并向其附加canvas元素,但它们是空的,没有任何内容。 canvasClone()函数来自:Appending a div containing canvas is not working

并且是:

function canvasClone(c1) {
  var c2 = document.createElement('canvas');
  c2.width=c1.width;
  c2.height=c1.height;
  c2.getContext("2d").drawImage(c1, 0,0);
  return c2;
}

我在控制台中看到的唯一警告信息是:

enter image description here

任何建议都将不胜感激。

  

更新

我也试过了:

let ctx =  c1.getContext("2d");
let imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
c2.getContext("2d").putImageData(imageData, 0, 0);

没有任何反应,没有工作

  

更新

我尝试了以下操作,考虑到我可以使用回调函数,但它仍然不成功:

let svg = d3.select("div#main svg").node();
SVG2Bitmap(svg, function(canvas) {
  this.props.datum.map((clusterObj, idx) => {
    let canvasId = "div#canvas" + idx;
    let clonedCanvas = this.canvasClone(canvas);
    d3.select(canvasId)
      .append(function() {
        return clonedCanvas;
      });
  })
});

1 个答案:

答案 0 :(得分:1)

我很抱歉,在编写此脚本时我做出了错误的设计选择......

这个脚本的重点是加载svg元素及其子元素使用的所有外部资源,以便创建一个独立的文档,可以通过drawImage方法绘制。

这意味着整个过程总是异步的,因此我的想法是传递除了回调函数以外的其他东西没什么意义,而且当我甚至不允许一种方法传递两个接收器元素时strong>和一个回调函数......

首先,对于我在这个已经死亡的项目中糟糕的设计选择感到抱歉。如果我不得不改写它(如果我将来有一些时间,也许我会这样做),我可能会坚持获取外部资产并将其包含在svg中,让用户选择他们想要做的事情之后它。

但如果您不想自己查看这些丑陋的代码,可以轻松解决问题。

脚本接受一个回调函数作为接收器,第一个参数将是一个新的<canvas>,并且已经在其上绘制了svg。

&#13;
&#13;
const this_props_datum = new Array(5).fill('foo');

let svg = d3.select("div#main svg").node();
SVG2Bitmap(svg, function callback(canvas) {
  this_props_datum.map((clusterObj, idx) => {
    let canvasId = "div#canvas" + idx;
    let clonedCanvas = this.canvasClone(canvas);
    d3.select(canvasId)
      .append(function() {
        return clonedCanvas;
      });
  })
});

function canvasClone(c1) {
  var c2 = document.createElement('canvas');
  c2.width = c1.width;
  c2.height = c1.height;
  c2.getContext("2d").drawImage(c1, 0, 0);
  return c2;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdn.rawgit.com/Kaiido/SVG2Bitmap/a4ff9a91/SVG2Bitmap.min.js"></script>

<div id="main">
  <svg width=100 height=100 viewBox="0 0 40 40">
    <circle cx=20 cy=20 r="20" fill="url(#patt)"/>
  </svg>
</div>
<div id="canvas0"></div>
<div id="canvas1"></div>
<div id="canvas2"></div>
<div id="canvas3"></div>
<div id="canvas4"></div>

<!-- just to make the script useful... -->
<svg width="0" height="0" style="position:aboslute;z-index:-1;opacity:0">
  <defs>
  <pattern id="patt" x="0" y="0" width=".25" height=".25">
    <image width="10" height="10" xlink:href="https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg"/>
</pattern>
</defs>
</svg>
&#13;
&#13;
&#13;