圖片服務器需要配置Access-Control-Allow-Origin
當需要需要對canvas圖片進行getImageData()或toDataURL()操作的時候,跨域問題就出來了。圖片服務器需要配置Access-Control-Allow-Origin信息,例如:
如PHP添加響應頭信息,*通配符表示允許任意域名:
header("Access-Control-Allow-Origin: *");
//或者指定域名
header("Access-Control-Allow-Origin: www.xxx.com");
此時,Chrome瀏覽器就不會有Access-Control-Allow-Origin相關的錯誤信息了,但是,還會有其他的跨域錯誤信息
canvas圖片getImageData cross-origin跨域問題
對於跨域的圖片,只要能夠在網頁中正常顯示出來,就可以使用canvas的drawImage() API繪制出來。但是如果你想更進一步,通過getImageData()方法獲取圖片的完整的像素信息,則多半會出錯:
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://vip.itzlm.cn/images/canvas.jpg';
在Chrome瀏覽器下顯示如下錯誤:
Uncaught DOMException: Failed to execute ‘getImageData’ on ‘CanvasRenderingContext2D’: The canvas has been tainted by cross-origin data.
如果使用的是canvas.toDataURL()方法,則會報:
Failed to execute ‘toDataURL’on’HTMLCanvasElement’: Tainted canvased may not be exported
原因其實都是一樣的,跨域導致。
那有沒有什么辦法可以解決這個問題呢?可以試試crossOrigin屬性
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://vip.itzlm.cn/images/canvas.jpg';
增加一個img.crossOrigin = ''即可,雖然JS代碼這里設置的是空字符串,實際上起作用的屬性值是anonymous
crossOrigin可以有下面兩個值:
關鍵字 | 釋義 |
anonymous | 元素的跨域資源請求不需要憑證標志設置 |
use-credentials | 元素的跨域資源請求需要憑證標志設置,意味着該請求需要提供憑證 |
其中,只要crossOrigin的屬性值不是use-credentials,全部都會解析為anonymous,包括空字符串,包括類似'abc'這樣的字符
img.crossOrigin = 'abc';
console.log(img.crossOrigin); // 結果是'anonymous'
有一點需要注意,那就是雖然沒有crossOrigin屬性,和設置crossOrigin="use-credentials"在默認情況下都會報跨域出錯,但是性質上卻不一樣,兩者有較大區別
crossOrigin兼容性
IE11+(IE Edge),Safari,Chrome,Firefox瀏覽器均支持,IE9和IE10會報SecurityError安全錯誤
crossOrigin=anonymous相對於告訴對方服務器,你不需要帶任何非匿名信息過來。例如cookie,因此,當前瀏覽器肯定是安全的
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();