Canvas引入跨域的图片导致toDataURL()报错的问题的解决

  • Post category:http

Canvas是HTML5新增的一个绘图标签,可以通过JavaScript在其中绘制各种图形,并且还支持将绘制内容导出为图片。然而,在某些情况下,我们在Canvas中加载跨域的图片时,会造成toDataURL()方法报错,这是由于浏览器的安全策略所致。接下来,我将就此问题作出详细说明,并提供两条示例说明。

问题描述

在Canvas中通过toDataURL()方法将绘制内容导出为png或者jpeg图片,如果绘制内容中包含跨域的图片,通常会出现以下的错误提示:

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement':
Tainted canvases may not be exported.
at HTMLCanvasElement.toDataURL (<anonymous>)

此时,该方法无法正常执行,因此无法将绘制内容导出为图片。

问题原因

当Canvas中绘制的内容中包含跨域的图片时,浏览器通常会视其为不安全的资源。为了遵守同源策略,浏览器会禁止将跨域图片导出为图片。这是浏览器的安全机制所导致的。

解决方案

要解决这个问题,我们可以通过以下几种方法:

1. 使用代理服务器

使用代理服务器的方法是将跨域的图片通过代理服务器转发到本地,然后再在Canvas中加载本地图片。这样就可以避免跨域问题。以下是一个使用代理服务器的示例代码:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.crossOrigin = "Anonymous";

var img = new Image();
img.onload = function() {
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  var dataURL = canvas.toDataURL("image/png");
  console.log(dataURL);
};
img.src = "http://example.com/image.png";

// 使用代理服务器
var proxyUrl = "https://cors-anywhere.herokuapp.com/";
var imageUrl = "http://example.com/image.png";

var xhr = new XMLHttpRequest();
xhr.open("GET", proxyUrl + imageUrl, true);
xhr.responseType = "blob";
xhr.onload = function() {
  if (this.status === 200) {
    img.src = URL.createObjectURL(this.response);
  }
};
xhr.send();

2. 给图片添加CORS头

在跨域的图片请求时,给图片添加CORS头信息,这样浏览器就不会将其视为不安全的资源。以下是一个给图片添加CORS头的示例代码:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function() {
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  var dataURL = canvas.toDataURL("image/png");
  console.log(dataURL);
};
img.src = "http://example.com/image.png";

以上是两种解决Canvas引入跨域的图片导致toDataURL()报错的问题的方法,开发者可以根据自己的情况选择更适合自己的方法来解决问题。