今天我們來說說在開發(fā)中比較常談及的問題,那就是跨域問題,我們就來說說在:“html5中如何解決canvas圖片getImageData,toDataURL跨域問題?”這個問題吧!
一、首先,圖片服務(wù)器需要配置Access-Control-Allow-Origin
一般團(tuán)隊(duì)都會有一個專門域名放置靜態(tài)資源,例如騰訊是 gtimg.com,百度是 bdimg.com;或者很多團(tuán)隊(duì)使用的是騰訊云或者阿里云的服務(wù)。
而主頁面所在域名往往不一樣,當(dāng)需要需要對 canvas 圖片進(jìn)行? getImageData()
?或?toDataURL()
?操作的時候,跨域問題就出來了,而且跨域問題還不止一層。
首先,第一步,圖片服務(wù)器需要配置?Access-Control-Allow-Origin
?信息,例如:
如PHP添加響應(yīng)頭信息,*通配符表示允許任意域名:
header("Access-Control-Allow-Origin: *");
或者指定域名:
header("Access-Control-Allow-Origin: www.zhangxinxu.com");
此時,Chrome 瀏覽器就不會有 ?Access-Control-Allow-Origin
?相關(guān)的錯誤信息了,但是,還會有其他的跨域錯誤信息。
二、canvas圖片getImageData cross-origin跨域問題
對于跨域的圖片,只要能夠在網(wǎng)頁中正常顯示出來,就可以使用 canvas 的?drawImage()
??API
?繪制出來。但是如果你想更進(jìn)一步,通過?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';';
結(jié)果在Chrome瀏覽器下顯示如下錯誤:
Uncaught DOMException: Failed to execute ‘getImageData’ on ‘CanvasRenderingContext2D’: The canvas has been tainted by cross-origin data.
Firefox瀏覽器錯誤為:
SecurityError: The operation is insecure.
如果使用的是canvas.toDataURL()方法,則會報:
Failed to execute ‘toDataURL’ on ’HTMLCanvasElement’: Tainted canvased may not be exported
原因其實(shí)都是一樣的,跨域?qū)е隆?/p>
那有沒有什么辦法可以解決這個問題呢?
可以試試 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://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
增加一個img.crossOrigin = ''即可,雖然JS代碼這里設(shè)置的是空字符串,實(shí)際上起作用的屬性值是 anonymous。
?crossOrigin
?可以有下面兩個值:
關(guān)鍵字 | 釋義 |
---|---|
anonymous | 元素的跨域資源請求不需要憑證標(biāo)志設(shè)置。 |
use-credentials | 元素的跨域資源請求需要憑證標(biāo)志設(shè)置,意味著該請求需要提供憑證。 |
其中,只要 crossOrigin 的屬性值不是 use-credentials,全部都會解析為 anonymous,包括空字符串,包括類似'abc'這樣的字符。
例如:
img.crossOrigin = 'abc';
console.log(img.crossOrigin); // 結(jié)果是'anonymous'
另外還有一點(diǎn)需要注意,那就是雖然沒有 crossOrigin 屬性,和設(shè)置 crossOrigin="use-credentials" 在默認(rèn)情況下都會報跨域出錯,但是性質(zhì)上卻不一樣,兩者有較大區(qū)別。
crossOrigin兼容性
IE11+(IE Edge),Safari,Chrome,F(xiàn)irefox瀏覽器均支持,IE9和IE10會報SecurityError安全錯誤,如下截圖:
四、crossOrigin屬性為什么可以解決資源跨域問題?
crossOrigin=anonymous相對于告訴對方服務(wù)器,你不需要帶任何非匿名信息過來。例如cookie,因此,當(dāng)前瀏覽器肯定是安全的。
就好比你要去別人家里拿一件衣服,crossOrigin=anonymous相對于告訴對方,我只要衣服,其他都不要。如果不說,可能對方在衣服里放個竊聽器什么的,就不安全了,瀏覽器就會阻止。
五、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 ...
// 圖片用完后記得釋放內(nèi)存
URL.revokeObjectURL(url);
};
img.src = url;
};
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.send();
此方法不僅IE10瀏覽器OK,原本支持crossOrigin的諸位瀏覽器也是支持的。
也就多走一個ajax請求,還可以!
根據(jù),根據(jù)實(shí)踐發(fā)現(xiàn),在IE瀏覽器下,如果請求的圖片過大,幾千像素那種,圖片會加載失敗,我猜是超過了blob尺寸限制。
六、結(jié)束語
那么這就是有關(guān)于:“html5中如何解決canvas圖片getImageData,toDataURL跨域問題?”這個問的相關(guān)內(nèi)容,當(dāng)然更多的相關(guān)內(nèi)容我們都可以在W3Cschool中進(jìn)行學(xué)習(xí)和了解。