一個關(guān)于image訪問圖片跨域的問題

一蒸甜、背景

項目中遇到一個問題,同一個圖片在 dom 節(jié)點中使用了 <img> 標簽來加載余佛,同時由于項目使用了 ThreeJS 3D 渲染引擎柠新,在加載紋理時使用了 TextureLoader 來加載了同一張圖片,而由于圖片是在阿里云服務(wù)器上的辉巡,所以最后報出了如下錯誤恨憎,意思是在訪問圖片時出現(xiàn)了跨域問題:


image 跨域錯誤

二、問題梳理

2.1 關(guān)于圖片的加載

圖片是來自于阿里云服務(wù)器的郊楣,和本地 localhost 必然存在跨域問題憔恳。通過 dom 節(jié)點的 <img> 標簽來直接訪問是沒有問題,因為瀏覽器本身不會有跨域問題净蚤。問題出在通過 TextureLoader 來加載圖片時出現(xiàn)了跨域問題钥组。查看了 TextureLoader 的源碼,發(fā)現(xiàn)其進一步使用了 ImageLoader 來加載圖片今瀑,加載圖片的代碼大致如下:

crossOrigin: 'anonymous',
......
var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
......
if ( url.substr( 0, 5 ) !== 'data:' ) {

            if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;

        }
......
image.src = url;

這段代碼所描述的大致思路是:

  1. 通過JS代碼程梦,創(chuàng)建一個 img 的 dom element,然后使用這個 element 來加載圖片橘荠。
  2. 默認情況下屿附,設(shè)置了 crossOrigin 的跨域?qū)傩詾?'anonymous'。

所以哥童,問題的關(guān)鍵在于挺份,同一張圖片,先用 <img> 標簽去加載了贮懈,然后再在 JS 代碼中匀泊,創(chuàng)建一個 <img> 并且設(shè)置了 crossOrigin 的跨域?qū)傩詾?'anonymous'影暴,那么在 JS 中創(chuàng)建的 <img> 就會出現(xiàn)訪問圖片而產(chǎn)生跨域的問題。

2.2 關(guān)于 crossOrigin

關(guān)于 crossOrigin探赫,我們看看 MDN 的解釋型宙。

crossOrigin

這段話,用我自己的理解來解釋一下:

  1. 加了 crossorigin 屬性伦吠,則表明圖片就一定會按照 CORS 來請求圖片妆兑。而通過CORS 請求到的圖片可以再次被復(fù)用到 canvas 上進行繪制。換言之毛仪,如果不加 crossorigin 屬性的話搁嗓,那么圖片是不能再次被復(fù)用到 canvas 上去的。
  2. 可以設(shè)置的值有 anonymous 以及 use-credentials箱靴,2 個 value 的作用都是設(shè)置通過 CORS 來請求圖片腺逛,區(qū)別在于 use-credentials 是加了證書的 CORS。
  3. 如果默認用戶不進行任何設(shè)置衡怀,那么就不會發(fā)起 CORS 請求棍矛。但如果設(shè)置了除 anonymous 和 use-credentials 以外的其他值,包括空字串在內(nèi)抛杨,默認會當作 anonymous來處理够委。

2.3 問題總結(jié)

通過前面 2 點的梳理,我們得出如下結(jié)論:

  1. 通過 <img> 加載的圖片怖现,瀏覽器默認情況下會將其緩存起來茁帽。
  2. 當我們從 JS 的代碼中創(chuàng)建的 <img> 再去訪問同一個圖片時,瀏覽器就不會再發(fā)起新的請求屈嗤,而是直接訪問緩存的圖片潘拨。但是由于 JS 中的 <img> 設(shè)置了 crossorigin,也就意味著它將要以 CORS 的方式請求饶号,但緩存中的圖片顯然不是的铁追,所以瀏覽器直接就拒絕了。連網(wǎng)絡(luò)請求都沒有發(fā)起讨韭。
  3. 在 Chrome 的調(diào)試器中脂信,在 network 面板中癣蟋,我們勾選了 disable cache 選項透硝,驗證了問題確實如第 2 點所述,瀏覽器這時發(fā)起了請求并且 JS 的 <img> 也能正常請求到圖片疯搅。

三濒生、解決問題

前面通過勾選 disable cache 來避免瀏覽器使用緩存圖片而解決了問題,但實際用戶不會這樣使用啊幔欧。根據(jù)前面的梳理罪治,<img> 不跨域請求丽声,而 JS 中的 <img> 跨域請求,所以不能訪問緩存觉义,那么是不是可以將 JS 中的 <img> 也設(shè)置成不跨域呢雁社,于是將 JS 中的 <img> 的 crossorigin 設(shè)置為 undefine,結(jié)果圖片是可以加載了晒骇,但又得到如下錯誤霉撵。

image.png

這段錯誤的意思是,這一個來自于CORS 的圖片洪囤,是不可以再次被復(fù)用到 canvas 上去的徒坡。這就驗證了關(guān)于 crossorigin 中的第 1 點。

既然 <img> 和 JS 中的 <img> 都不加 crossorigin不能解決 canvas 重用的問題瘤缩,那么在兩邊同時都加上 crossorigin 呢喇完?果然,在 <img> 中和 JS 中的 <img> 都加上 crossorigin = "anonymous"剥啤,圖片可以正常加了锦溪,同時也可以被復(fù)用到 <canvas> 上去了。

另外府怯,需要注意的 2 個小問題是:

  1. 服務(wù)器必須加上字段海洼,否則,客戶端設(shè)置了也是沒用的富腊。

Access-Control-Allow-Origin: *

  1. 如果是已經(jīng)出了問題坏逢,你才看到這篇文章,或者才去想到這么解決赘被。那么要記得先清理一下游覽器所緩存的圖片是整。否則你就會發(fā)現(xiàn),有的圖片可以訪問民假,而有的不可以浮入。那是因為緩存中之前存儲了未 CORS 的圖片。

四羊异、總結(jié)

前面說了一框事秀,只是想把這個過程完整的記錄下來。整個問題的總結(jié)是:

  1. 同一張圖片或者同一個地址野舶,同時被 <img> 所訪問易迹,而隨后后又會被如 JS 中去訪問。而圖片存儲的地址是跨域的平道,那么就可能因為緩存問題而導(dǎo)致 JS 中的訪問出現(xiàn)跨域問題睹欲。
  2. 解決的辦法是讓 <img> 標簽和 JS 中的訪問都走跨域訪問的方式,這樣既可以解決跨域訪問的問題,也可以解決跨域圖片在 canvas 中的復(fù)用窘疮。

最后袋哼,感謝你能讀到并讀完此文章,如果分析的過程中存在錯誤或者疑問都歡迎留言討論闸衫。如果我的分享能夠幫助到你涛贯,還請記得幫忙點個贊吧,謝謝蔚出。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疫蔓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子身冬,更是在濱河造成了極大的恐慌衅胀,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酥筝,死亡現(xiàn)場離奇詭異滚躯,居然都是意外死亡,警方通過查閱死者的電腦和手機嘿歌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門掸掏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宙帝,你說我怎么就攤上這事丧凤。” “怎么了步脓?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵愿待,是天一觀的道長。 經(jīng)常有香客問我靴患,道長仍侥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任鸳君,我火速辦了婚禮农渊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘或颊。我一直安慰自己砸紊,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布囱挑。 她就那樣靜靜地躺著醉顽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪看铆。 梳的紋絲不亂的頭發(fā)上徽鼎,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音弹惦,去河邊找鬼否淤。 笑死,一個胖子當著我的面吹牛棠隐,可吹牛的內(nèi)容都是我干的石抡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼助泽,長吁一口氣:“原來是場噩夢啊……” “哼啰扛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嗡贺,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤隐解,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后诫睬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體煞茫,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年摄凡,在試婚紗的時候發(fā)現(xiàn)自己被綠了续徽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡亲澡,死狀恐怖钦扭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情床绪,我是刑警寧澤客情,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站癞己,受9級特大地震影響裹匙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜末秃,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一概页、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧练慕,春花似錦惰匙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至劲阎,卻和暖如春绘盟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工龄毡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吠卷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓沦零,卻偏偏與公主長得像祭隔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子路操,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容