crossOrigin属性解决canvas图片getImageData跨域

这篇文章发布于 2018年02月10日,星期六,23:27,归类于 canvas相关。 阅读 5162 次, 今日 6 次

一、canvas图片getImageData跨域问题

对于跨域的图片,只要能够在网页中正常显示出来,就可以使用canvas的drawImage() API绘制出来。但是如果你想更进一步,通过getImageData()方法获取图片的完整的像素信息,则多半会出错。

举例来说,使用下面代码获取github上的自己头像图片信息:

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');

var img = new Image();
img.onload = function () {
    context.drawImage(this, 0, 0);
    context.getImageData(0, 0, this.width, this.height);
};
img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';

结果在Chrome浏览器下显示如下错误:

Uncaught DOMException: Failed to execute ‘getImageData’ on ‘CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

出错信息截图

Firefox浏览器错误为:

SecurityError: The operation is insecure.

那有没有什么办法可以解决这个问题呢?

一、HTML crossOrigin属性解决资源跨域问题

在HTML5中,有些元素提供了支持CORS(Cross-Origin Resource Sharing)(跨域资源共享)的属性,这些元素包括<img><video><script>等,而提供的属性名就是crossOrigin属性。

因此,上面的跨域问题可以这么处理:

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');

var img = new Image();
img.crossOrigin = '';
img.onload = function () {
    context.drawImage(this, 0, 0);
    context.getImageData(0, 0, this.width, this.height);
};
img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';

增加一个img.crossOrigin = ''即可,虽然JS代码这里设置的是空字符串,实际上起作用的属性值是anonymous

crossOrigin可以有下面两个值:

关键字 释义
anonymous 元素的跨域资源请求不需要凭证标志设置。
use-credentials 元素的跨域资源请求需要凭证标志设置,意味着该请求需要提供凭证。

其中,只要crossOrigin的属性值不是use-credentials,全部都会解析为anonymous,包括空字符串,包括类似'abc'这样的字符。

例如:

img.crossOrigin = 'abc';
console.log(img.crossOrigin);    // 结果是'anonymous'

crossOrigin解析为anonymous

另外还有一点需要注意,那就是虽然没有crossOrigin属性,和设置crossOrigin="use-credentials"在默认情况下都会报跨域出错,但是性质上却不一样,两者有较大区别。

crossOrigin兼容性

IE11+,Safari,Chrome,Firefox浏览器均支持,IE9和IE10会报SecurityError安全错误,如下截图:

三、结束语

最近工作中学到的一点小经验,希望可以帮到遇到类似问题的小伙伴。

感谢阅读!

(本篇完)

分享到:

赞助商推荐(我也要赞助)

想学到点真东西? ×
如果你有1~3年前端开发经验,不妨 ×
想高薪入职阿里? ×
想要免费一对一编程辅导? ×


发表评论(目前4 条评论)

  1. 说道:

    很不错

  2. 刘昭廷说道:

    每天关注鑫大神的空间,自己的经验每天都会涨一点~

  3. 敖爽说道:

    虽然有crossOrigin这个属性 , 但是要达到正常的getImageData还是需要服务器那边支持跨域才行吧~ , 就像上一篇文章里说的那样

  4. 小白说道:

    前辈你好,最近在做audio的canvas频谱图,
    //连接方式:source → analyser → destination
    遇到的问题就是使用本地static音频文件的时候正常,用网上的连接就会报跨域问题,我找了一些资料,他们给的解决也是crossorigin,但是设置之后就被403了(谷歌也是版本皆为最新)
    火狐报错:
    已拦截跨源请求:同源策略禁止读取位于 http://m10.music.126.net/20180211152619/984afca11628ed48d15703a6b9f83383/ymusic/1370/452a/f846/a98bb4e0b0374d5b25c0694c534d5056.mp3 的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin’)。
    没有设置crossorigin的情况
    传递到 createMediaElementSource 的 HTMLMediaElement 有一个跨源资源,该节点将输出无声。