Preload方法
搜到一個Image Preload的方案肌访,簡單粗暴
const img = new Image();
img.src = url;
執(zhí)行以上代碼纯陨,這個url的圖片就會被預(yù)加載政溃,想要使用的時候趾访,img.onload 即可,甚至重新new一個Image對象董虱,賦值相同的url扼鞋,都是可以復(fù)用的。
Canvas跨域報錯
但是直接用會在canvas里會有個坑愤诱。
當(dāng)我使用canvas的 ctx.getImageData 會得到這個報錯云头,直譯過來就是有跨域數(shù)據(jù)污染了canvas。
增加一個 img.crossOrigin = ""; 即可淫半。雖然這里設(shè)置的是空字符串溃槐,實際上起作用的屬性值是anonymous。
crossOrigin可以有下面兩個值:
關(guān)鍵字 | 含義 |
---|---|
anonymous | 元素的跨域資源請求不需要憑證標(biāo)志設(shè)置科吭。 |
use-credentials | 元素的跨域資源請求需要憑證標(biāo)志設(shè)置昏滴,意味著該請求需要提供憑證猴鲫。 |
實際上,只要crossOrigin的屬性值不是use-credentials谣殊,全部都會解析為anonymous拂共,包括空字符串,包括類似'abc'這樣的字符姻几。
https://www.zhangxinxu.com/wordpress/2018/02/crossorigin-canvas-getimagedata-cors/
這樣操作后就可以快樂的預(yù)加載圖片宜狐,并且和Canvas愉快的玩耍了。
圖片好像加載了兩次
有一些圖片蛇捌,我不僅僅在JS里用來用去肌厨,還在HTML中img標(biāo)簽用到了,然而我發(fā)現(xiàn)這圖請求了兩次豁陆。
難道img標(biāo)簽和js中的 Image 對象不能共用這個預(yù)加載柑爸??
或者不應(yīng)該用src傳鏈接盒音?而是img標(biāo)簽有什么別的屬性可以接收Image對象表鳍?
Image對象不就是img HTMLElement嗎?祥诽?譬圣?
到底是為什么呢。雄坪。厘熟。
很細(xì)小的區(qū)別就是其中一個多了個Origin字段:
我直接去查了img標(biāo)簽有哪些屬性,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img
發(fā)現(xiàn)了一個叫crossorigin的屬性维哈。绳姨。
沒錯,安排上anonymous阔挠,就可以省掉多余的那次請求了飘庄。
<img :src="currentBgUrl" alt="背景圖" crossorigin="anonymous">
優(yōu)化預(yù)加載圖片數(shù)組
一開始直接一個forEach,每個url搞個對象預(yù)加載一下购撼,目的是達(dá)到了跪削。但還可以根據(jù)場景再優(yōu)化一下。
考慮到這列圖片用在刮刮樂上迂求,圖片是按順序展示的碾盐,第一張圖沒加載出來,第108張圖根本是用不到的揩局。
所以:
preloadImages(imageUrls, index = 0) {
if (imageUrls && imageUrls.length > index) {
const img = new Image();
img.onload = () => {
preloadImages(imageUrls, index + 1);
};
img.crossOrigin = "";
img.src = imageUrls[index];
}
}
參考 https://www.photo-mark.com/notes/image-preloading/
盜一下別人的測試結(jié)果
The canonical preloader shaved 1.5 seconds off the total time. But that’s not the most important statistic in this case. The top line of each chart represents the download time of the next image in the gallery — the one 90% of my users will ask for next. Using the canonical preloader code with a moderately slow connection, that image is not available to our viewer until 14.27 seconds after the page loads even though it was first in line and began downloading immediately after the main page loaded. This is because it is sharing bandwidth with a bunch of other files as you can see in the chart. With the sequential download this image has the full bandwidth to itself and is ready in 1.46 seconds — almost 1000% faster. For our most common use case this is an immense improvement.
簡言之毫玖,并行加載確實省一點點點點點點時間(24.01秒 VS 25.44秒),但是跟提升的用戶體驗比起來顯得微不足道。
我自己也測試了一下效果孕豹,理論上來說涩盾,讓前面的圖片先加載顯然更加有意義。當(dāng)然励背,在圖片較小網(wǎng)速較快的情況下春霍,這兩種體驗的差距幾乎忽略不計∫睹迹總而言之址儒,串行加載不虧。
用戶點擊切換圖片的時候衅疙,好像還是又請求了莲趣?
不得不說,加載完成后饱溢,等待用戶交互喧伞,等到用戶點擊切換其他圖片時,又發(fā)了一個請求绩郎,明明已經(jīng)preload了潘鲫。
我只好將所有圖片preload時push到一個cache數(shù)組掛在vue實例data中,果然OK了肋杖。完美實現(xiàn)溉仑。
我估計是preload完img又被GC了…
https://stackoverflow.com/questions/15736501/non-attached-image-onload-garbage-collection