Preload方法
搜到一個(gè)Image Preload的方案,簡(jiǎn)單粗暴
const img = new Image();
img.src = url;
執(zhí)行以上代碼,這個(gè)url的圖片就會(huì)被預(yù)加載,想要使用的時(shí)候,img.onload 即可,甚至重新new一個(gè)Image對(duì)象,賦值相同的url,都是可以復(fù)用的。
Canvas跨域報(bào)錯(cuò)
但是直接用會(huì)在canvas里會(huì)有個(gè)坑。

當(dāng)我使用canvas的 ctx.getImageData 會(huì)得到這個(gè)報(bào)錯(cuò),直譯過(guò)來(lái)就是有跨域數(shù)據(jù)污染了canvas。
增加一個(gè) img.crossOrigin = ""; 即可。雖然這里設(shè)置的是空字符串,實(shí)際上起作用的屬性值是anonymous。
crossOrigin可以有下面兩個(gè)值:
| 關(guān)鍵字 | 含義 |
|---|---|
| anonymous | 元素的跨域資源請(qǐng)求不需要憑證標(biāo)志設(shè)置。 |
| use-credentials | 元素的跨域資源請(qǐng)求需要憑證標(biāo)志設(shè)置,意味著該請(qǐng)求需要提供憑證。 |
實(shí)際上,只要crossOrigin的屬性值不是use-credentials,全部都會(huì)解析為anonymous,包括空字符串,包括類似'abc'這樣的字符。
https://www.zhangxinxu.com/wordpress/2018/02/crossorigin-canvas-getimagedata-cors/
這樣操作后就可以快樂(lè)的預(yù)加載圖片,并且和Canvas愉快的玩耍了。
圖片好像加載了兩次
有一些圖片,我不僅僅在JS里用來(lái)用去,還在HTML中img標(biāo)簽用到了,然而我發(fā)現(xiàn)這圖請(qǐng)求了兩次。

難道img標(biāo)簽和js中的 Image 對(duì)象不能共用這個(gè)預(yù)加載??
或者不應(yīng)該用src傳鏈接?而是img標(biāo)簽有什么別的屬性可以接收Image對(duì)象?
Image對(duì)象不就是img HTMLElement嗎???
到底是為什么呢。。。
很細(xì)小的區(qū)別就是其中一個(gè)多了個(gè)Origin字段:


我直接去查了img標(biāo)簽有哪些屬性,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img
發(fā)現(xiàn)了一個(gè)叫crossorigin的屬性。。
沒(méi)錯(cuò),安排上anonymous,就可以省掉多余的那次請(qǐng)求了。
<img :src="currentBgUrl" alt="背景圖" crossorigin="anonymous">
優(yōu)化預(yù)加載圖片數(shù)組
一開(kāi)始直接一個(gè)forEach,每個(gè)url搞個(gè)對(duì)象預(yù)加載一下,目的是達(dá)到了。但還可以根據(jù)場(chǎng)景再優(yōu)化一下。
考慮到這列圖片用在刮刮樂(lè)上,圖片是按順序展示的,第一張圖沒(méi)加載出來(lái),第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/

盜一下別人的測(cè)試結(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.
簡(jiǎn)言之,并行加載確實(shí)省一點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)時(shí)間(24.01秒 VS 25.44秒),但是跟提升的用戶體驗(yàn)比起來(lái)顯得微不足道。
我自己也測(cè)試了一下效果,理論上來(lái)說(shuō),讓前面的圖片先加載顯然更加有意義。當(dāng)然,在圖片較小網(wǎng)速較快的情況下,這兩種體驗(yàn)的差距幾乎忽略不計(jì)??偠灾?,串行加載不虧。


用戶點(diǎn)擊切換圖片的時(shí)候,好像還是又請(qǐng)求了?
不得不說(shuō),加載完成后,等待用戶交互,等到用戶點(diǎn)擊切換其他圖片時(shí),又發(fā)了一個(gè)請(qǐng)求,明明已經(jīng)preload了。
我只好將所有圖片preload時(shí)push到一個(gè)cache數(shù)組掛在vue實(shí)例data中,果然OK了。完美實(shí)現(xiàn)。
我估計(jì)是preload完img又被GC了…
https://stackoverflow.com/questions/15736501/non-attached-image-onload-garbage-collection