以下に記述した機能は、現在一般的に使用されているほとんどすべてのブラウザーで画像をプリロードするのに十分ですか?
function preloadImage(url)
{
var img=new Image();
img.src=url;
}
ループして、preloadImage各URLの関数を呼び出す画像URLの配列があります。
(new Image()).src = url;
new Image().src = url;
以下に記述した機能は、現在一般的に使用されているほとんどすべてのブラウザーで画像をプリロードするのに十分ですか?
function preloadImage(url)
{
var img=new Image();
img.src=url;
}
ループして、preloadImage各URLの関数を呼び出す画像URLの配列があります。
(new Image()).src = url;
new Image().src = url;
回答:
はい。これはすべての主要なブラウザで動作するはずです。
これを試してみてください。
var images = [];
function preload() {
for (var i = 0; i < arguments.length; i++) {
images[i] = new Image();
images[i].src = preload.arguments[i];
}
}
//-- usage --//
preload(
"http://domain.tld/gallery/image-001.jpg",
"http://domain.tld/gallery/image-002.jpg",
"http://domain.tld/gallery/image-003.jpg"
)
ソース:http : //perishablepress.com/3-ways-preload-images-css-javascript-ajax/
onload画像のハンドラはありません
onload状態を処理する必要があるか、メモリ内の画像をインスタンス化しているだけです。
for (var i = 0.....
var
私の場合、onloadイベントのコールバックを関数に追加すると便利でした。
function preloadImage(url, callback)
{
var img=new Image();
img.src=url;
img.onload = callback;
}
そして、すべてのコールバックでプリロードされる画像へのURLの配列の場合のためにそれをラップします:https : //jsfiddle.net/4r0Luoy7/
function preloadImages(urls, allImagesLoadedCallback){
var loadedCounter = 0;
var toBeLoadedNumber = urls.length;
urls.forEach(function(url){
preloadImage(url, function(){
loadedCounter++;
console.log('Number of loaded images: ' + loadedCounter);
if(loadedCounter == toBeLoadedNumber){
allImagesLoadedCallback();
}
});
});
function preloadImage(url, anImageLoadedCallback){
var img = new Image();
img.onload = anImageLoadedCallback;
img.src = url;
}
}
// Let's call it:
preloadImages([
'//upload.wikimedia.org/wikipedia/commons/d/da/Internet2.jpg',
'//www.csee.umbc.edu/wp-content/uploads/2011/08/www.jpg'
], function(){
console.log('All images were loaded');
});
CSS2の代替:http : //www.thecssninja.com/css/even-better-image-preloading-with-css2
body:after {
content: url(img01.jpg) url(img02.jpg) url(img03.jpg);
display: none;
}
CSS3代替:https : //perishablepress.com/preload-images-css3/ (H / T Linh Dam)
.preload-images {
display: none;
width: 0;
height: 0;
background: url(img01.jpg),
url(img02.jpg),
url(img03.jpg);
}
注:コンテナ内の画像display:noneはプリロードされない場合があります。おそらく、visibility:hiddenの方がうまく機能しますが、これはテストしていません。これを指摘してくれたMarco Del Valleに感謝します
display: noneはプリロードされません。
display: none、(2)を使用しなかったwidth/height: 0、(3)配置no-repeat、および画像が外側になるような位置(画像が-<width>px -<height>pxそこに到達するため、画像がすべて100pxの場合あまりの高さや、使用することができます0 -100pxつまり、url(...) no-repeat 0 -100px。
可能性のある問題を防ぐために、try / catchを使用することをお勧めします。
OOP:
var preloadImage = function (url) {
try {
var _img = new Image();
_img.src = url;
} catch (e) { }
}
標準:
function preloadImage (url) {
try {
var _img = new Image();
_img.src = url;
} catch (e) { }
}
また、私はDOMを愛していますが、古い愚かなブラウザーはDOMの使用に問題がある可能性があるため、freedevの貢献に反して、完全にIMHOを回避してください。Image()は古いごみブラウザでのサポートが向上しています。
このアプローチはもう少し複雑です。ここでは、プリロードされたすべてのイメージをコンテナーに格納します。divの場合もあります。そして、画像を表示したり、DOM内で適切な位置に移動したりできます。
function preloadImg(containerId, imgUrl, imageId) {
var i = document.createElement('img'); // or new Image()
i.id = imageId;
i.onload = function() {
var container = document.getElementById(containerId);
container.appendChild(this);
};
i.src = imgUrl;
}
const preloadImage = src =>
new Promise(r => {
const image = new Image()
image.onload = r
image.onerror = r
image.src = src
})
// Preload an image
await preloadImage('https://picsum.photos/100/100')
// Preload a bunch of images in parallel
await Promise.all(images.map(x => preloadImage(x.src)))
この意志の仕事をはい、しかし、ブラウザがします制限します(4-8間)の実際の呼び出し、したがってないキャッシュ/ PRELOAD全ての所望の画像を。
これを行うより良い方法は、次のようにイメージを使用する前にonloadを呼び出すことです。
function (imageUrls, index) {
var img = new Image();
img.onload = function () {
console.log('isCached: ' + isCached(imageUrls[index]));
*DoSomething..*
img.src = imageUrls[index]
}
function isCached(imgUrl) {
var img = new Image();
img.src = imgUrl;
return img.complete || (img .width + img .height) > 0;
}
注:これは、Babelのようなトランスパイラーを使用している場合にも機能します。
'use strict';
function imageLoaded(src, alt = '') {
return new Promise(function(resolve) {
const image = document.createElement('img');
image.setAttribute('alt', alt);
image.setAttribute('src', src);
image.addEventListener('load', function() {
resolve(image);
});
});
}
async function runExample() {
console.log("Fetching my cat's image...");
const myCat = await imageLoaded('https://placekitten.com/500');
console.log("My cat's image is ready! Now is the time to load my dog's image...");
const myDog = await imageLoaded('https://placedog.net/500');
console.log('Whoa! This is now the time to enable my galery.');
document.body.appendChild(myCat);
document.body.appendChild(myDog);
}
runExample();
すべての画像が読み込まれるのを待つこともできます。
async function runExample() {
const [myCat, myDog] = [
await imageLoaded('https://placekitten.com/500'),
await imageLoaded('https://placedog.net/500')
];
document.body.appendChild(myCat);
document.body.appendChild(myDog);
}
または、Promise.allそれらを並行してロードするために使用します。
async function runExample() {
const [myCat, myDog] = await Promise.all([
imageLoaded('https://placekitten.com/500'),
imageLoaded('https://placedog.net/500')
]);
document.body.appendChild(myCat);
document.body.appendChild(myDog);
}
問題のアプローチは、画像がダウンロードされてキャッシュされるのをトリガーするのに十分であることを確認できます(ブラウザが応答ヘッダーを介してそうすることを禁止している場合を除きます)。
これをテストするために、子猫の写真を提供する前にそれぞれが10秒間スリープするいくつかのエンドポイントを持つ小さなWebアプリケーションを作成しました。その後、私は2つの含まれているそのうちの一つのウェブページ、添加<script>子猫のそれぞれが使用してプリロードされたタグpreloadImage質問から機能、および他のその使用ページ上のすべての子猫含む<img>タグ。
上記のすべてのブラウザーで、最初にプリローダーページにアクセスし、しばらく待ってから<img>タグのあるページに移動すると、子猫がすぐにレンダリングされることがわかりました。これは、プリローダーがテストしたすべてのブラウザーのキャッシュに子猫を正常にロードしたことを示しています。
これをテストするために使用したアプリケーションは、https://github.com/ExplodingCabbage/preloadImage-testで確認または試すことができます。
特に、ループされる画像の数が、Robinの回答が示唆するのとは逆に、ブラウザが一度に行う並列リクエストの数を超える場合でも、この手法は上記のブラウザで機能することに注意してください。もちろん、画像のプリロードの速度は、ブラウザが送信する並列リクエストの数によって制限されますが、最終的には、呼び出す画像の各URLを要求preloadImage()します。
ブラウザは、head内のリンクタグを使用すると最適に動作します。
export function preloadImages (imageSources: string[]): void {
imageSources
.forEach(i => {
const linkEl = document.createElement('link');
linkEl.setAttribute('rel', 'preload');
linkEl.setAttribute('href', i);
linkEl.setAttribute('as', 'image');
document.head.appendChild(linkEl);
});
}
imgオブジェクトへの参照を、たとえば親スコープの配列に保持します。