解决canvas的getImageData 和 toDataURL跨域)
1. HTML加载图片跨域问题
通常我们在使用img标签的时候,外链图片资源是不会出现这种情况的。
当我们去是用脚本去加载一张图图片的在不同域的时候就会出现,图片资源的跨域的情况,这其实是浏览器的同源策略。
通常我们只需要在 ,被请求资源的服务器配置一下请求头即可
//如PHP添加响应头信息,*通配符表示允许任意域名:
header("Access-Control-Allow-Origin: *");
或者指定域名:
header("Access-Control-Allow-Origin: www.baidu.com");
2. HTML本地图片跨域问题
可以将本地图片转换成base64编码,直接把base64编码赋值给图片的src属性就可以简单的解决这个问题了。这种方式仅仅适用于图片,如果是视频的话,还是需要服务器端的配合。
3. canvas操作图片像素的跨域问题
对于跨域的图片,只要能够在网页中正常显示出来,就可以使用canvas的drawImage() API绘制出来。但是如果你想更进一步,通过getImageData()方法获取图片的完整的像素信息,则多半会出错。
报错:
Uncaught DOMException: Failed to execute ‘getImageData’ on ‘CanvasRenderingContext2D’: The canvas has been tainted by cross-origin data.
报错
SecurityError: The operation is insecure.
解决办法:
// canvas实现图片反转
window.onload = function(){
var cnv = document.getElementById('canvas');
var cxt = cnv.getContext('2d');
var image = new Image();
var url = 'https://img2.baidu.com/it/u=578436537,404719122&fm=26&fmt=auto';
// 给img加上时间戳
image.src = url + '?' + new Date().getTime();
// 给img设置crossOrigin属性解决跨域
image.setAttribute('crossOrigin', '');
image.onload = function () {
cxt.drawImage(image, 0, 0, 86, 108);
var imageData = cxt.getImageData(0, 0, 86, 108);
var data = imageData.data
for(var i=0;i<data.length;i+=4) {
data[i+0] = 255 - data[i+0];
data[i+1] = 255 - data[i+1];
data[i+2] = 255 - data[i+2];
}
cxt.putImageData(imageData, 96, 0);
}
}
crossOrigin兼容性 IE11+(IE Edge),Safari,Chrome,Firefox浏览器均支持,IE9和IE10会报SecurityError安全错误
2.1 IE10浏览器不支持crossOrigin怎么办?
我们请求图片的时候,不是直接通过new Image(),而是借助ajax和URL.createObjectURL()方法
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var url = URL.createObjectURL(this.response);
var img = new Image();
img.onload = function () {
// 此时你就可以使用canvas对img为所欲为了
// ... code ...
// 图片用完后记得释放内存
URL.revokeObjectURL(url);
};
img.src = url;
};
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.send();
2.2 crossOrigin属性为什么可以解决资源跨域问题?
crossOrigin=anonymous相对于告诉对方服务器,你不需要带任何非匿名信息过来。例如cookie,因此,当前浏览器肯定是安全的。
就好比你要去别人家里拿一件衣服,crossOrigin=anonymous相对于告诉对方,我只要衣服,其他都不要。如果不说,可能对方在衣服里放个窃听器什么的,就不安全了,浏览器就会阻止。
在HTML5中,一些 HTML 元素提供了对 CORS 的支持, 例如 audio、img、link、script 和 video 均有一个跨域属性 (crossOrigin property),它允许你配置元素获取数据的 CORS 请求。
在媒体元素上被使用的 crossorigin 内容属性是一个 CORS 设置属性。
关键字 | 描述 |
---|---|
anonymous | 对此元素的 CORS 请求将不设置凭据标志 |
se-credentials | 对此元素的CORS请求将设置凭证标志;这意味着请求将提供凭据。 |
“” | 设置一个空的值,如 crossorigin 或 crossorigin="",和设置 anonymous 的效果一样。 |
// 你可以使用下面的 <script> 元素告诉浏览器执行来自
// https://example.com/example-framework.js 的脚本且不发送用户凭据。
<script src="https://example.com/example-framework.js" crossorigin="anonymous"></script>
// 在获取需要用户凭据的 manifest 时,属性值必须设置为 use-credentials。即使是同源的情况。
<link rel="manifest" href="/app.webmanifest" crossorigin="use-credentials">