【问题标题】:TypeMismatchError in drawImage()drawImage() 中的 TypeMismatchError
【发布时间】:2015-06-04 20:06:03
【问题描述】:

我正在使用drawImage()。这是我的代码。 imDiv 包含一个内联 svg。

  var c =document.getElementById( 'cvs' );
  var ctx =c.getContext( '2d' );
  var img =document.getElementById( 'imDiv' );
   ctx.drawImage( img, 0, 0 );  //TypeMismatchError

我收到TypeMismatchError 错误。可能是什么原因,我该如何解决?

【问题讨论】:

  • 有人有什么建议吗?
  • imDiv是包含图片的div的id吗?如果是这样,这将不起作用 - 您需要提供图像元素本身,而不是包含它的 div。即使 div 设置了 background-image 属性,传递 div 元素仍然不起作用。您只能将img 元素或canvas 元素作为第一个参数传递给ctx.drawImage

标签: javascript jquery html canvas


【解决方案1】:

您必须先将 SVG 转换为图像,然后将图像绘制到画布上。

您需要考虑一些事项:

  • SVG 必须格式正确(想想 XML)
  • SVG 中的第一个元素必须是 xmlns 属性
  • 当涉及到foreignObject(嵌入 HTML 等)时,取决于浏览器的不同安全限制。它可以在某些(Firefox,没有外部引用)中工作,而其他一些则不是(例如 Chrome)。这目前处于真空状态,我们无法在客户端做太多事情

这是执行此操作的一种方法:

// Inline SVG:
var svg = document.querySelector('svg').outerHTML,  // make sure SVG tags are included
  canvas = document.querySelector('canvas'),        // target canvas
  ctx = canvas.getContext('2d');

// convert to image (see function below)
// converting to image is an asynchronous process, so we need a callback
svgToImage(svg, function(img) {

  // HERE you could insert the image to DOM:
  // var myElement = document.getElementById(elementID);
  // myElement.appendChild(img);
  
  // set canvas size = image
  canvas.width = img.width;
  canvas.height = img.height;

  // draw SVG-image to canvas
  ctx.drawImage(img, 0, 0);
});

// this will convert an inline SVG to a DATA-URI
function svgToImage(svg, callback) {
  var url = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg),
      img = new Image;

  // handle image loading, when done invoke callback
  img.onload = function() {
    callback(this);
  };

  img.src = url;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <linearGradient id="gradient">
    <stop offset="0%" stop-color="#00f" />
    <stop offset="100%" stop-color="#f70" />
  </linearGradient>
  <rect fill="url(#gradient)" x="0" y="0" width="100%" height="100%" />
</svg>

<br>
<canvas></canvas><br>

【讨论】:

  • 谢谢...这真的很棒。我有一个小问题,因为页面上有多个 svg。所以我尝试将svg = document.querySelector('svg').outerHTML,'canvas = document.querySelector('canvas'), 替换为var canvas = document.getElementById( 'cvs' ),svg = document.getElementById( 'imDiv' )。当我这样做时,url 的输出类似于data:image/svg+xml;utf8,%5object%20HTMLDivElement%5D。那么如何通过容器 DIV 定位特定的 svg,以及如何通过它的 ID 定位绘图画布?
  • @user3687622 你必须使用outerHTML来获取字符串内容,例如:svg = document.getElementById('cvs').outerHTML;。 outerHTML 包含您定位的元素的外部标签(即&lt;svg ...&gt;...&lt;/svg&gt;)。如果你不使用它,你只会得到元素 object 本身,它不能用作字符串。
  • 我只是在看你的 undo-redo js 插件——这真的很好。 :)
  • 又一个小问题。 img 指的是什么?如何在特定的画布中绘制它?例如:var img =document.getElementById( 'imDiv' ); 并使用 ctx.drawImage(img, 0, 0);
  • @user3687622 img 是在 svgToImage 中创建的图像元素。在回调中使用相同的 img 名称。您可以将其存储为全局值,并根据需要从那里使用它。也可以使用 someElement.appendChild(img) 将其直接插入 DOM,但在这种情况下,我建议先设置一个 ID (img.id = "img1"; ...appendChild(img))。但是由于无论如何您都需要异步处理它,因此最好从回调函数内部进行。
【解决方案2】:

目前,无法在画布上绘制 divsvg 元素。传递给context.drawImage() 的第一个参数必须是Image、画布,甚至是视频元素(使用svg 可能会导致TypeMismatchError)。

因此,您将使用getElementById() 检索文档上的实际Image,或使用new Image() 创建一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 2012-06-17
    • 2013-12-22
    • 1970-01-01
    • 2014-07-25
    • 2019-02-06
    • 1970-01-01
    相关资源
    最近更新 更多