最近、JavaScriptを使ってアニメーション機能を作りたいと思っています。アニメーションをスムーズにスムーズに再生するために、使用する画像素材をプリロードする必要があります。この機能を実装するプロセスを共有します
単一イメージのプリロード
最も一般的な実装方法は次のとおりです
function preloadImg(url) { var img = new Image(); img.src = url; if(img.complete) { //接下来可以使用图片了 //do something here } else { img.onload = function() { //接下来可以使用图片了 //do something here }; } }
まず、Image オブジェクトをインスタンス化します。値を img に設定し、img.src をパラメータ url で指定された画像アドレスに設定し、img の完全な属性を決定します。この画像のローカル キャッシュがある場合、値は true になります。この時点で、このイメージを直接操作します。ローカル キャッシュがない場合、値は false です。このとき、img の onload イベントを監視し、img に対する操作を onload コールバック関数に入れる必要があります。テスト後のこの解決策は、基本的に次のとおりです現在のすべてのブラウザと互換性
複数の画像のプリロード
アニメーションなどの関数には通常、多くの機能が含まれるため、多くのシナリオでは、単一の画像のプリロードではニーズを満たすことができません。次に、元の単一画像のプリロードに基づいて機能を改善します
function preloadImg(list) { var imgs = arguments[1] || [], //用于存储预加载好的图片资源 fn = arguments.cal lee; if(list.length == 0) { return imgs; } var img = new Image(); img.src = list[0]; if(img.complete) { imgs.push(img); list.shift(); fn(list, imgs); } else { img.onload = function() { imgs.push(img); list.shift(); fn(list, imgs); }; } } var list = [......], //此处省略一万个字符 imgs = preloadImg();
フレーム アニメーションでは、アニメーションの各フレームで使用される画像の順序を保証する必要があるため、このコードでは再帰を使用しますこのメソッドでは、前のピクチャがロードされた後に次のピクチャをロードします。ピクチャがロードされるたびに、ピクチャ リソースが imgs 配列に格納され、このピクチャのアドレスがアドレス配列リストから削除されます。リスト内で、再帰から抜け出して imgs 配列を返します。
アイデアは美しいですが、現実は残酷です。このコードには耐えられない問題が 2 つあります。
まず第一に、私はおそらくそうでしょう。ローカルにキャッシュされていない画像がある限り、imgs の保存操作は onload コールバック イベントに配置され、イベント監視も JavaScript の非同期操作の一種であるため、最後に返された imgs 配列は取得できません。 onload イベントのバインディング コールバック関数の後、preloadImg 関数は戻り値なしで終了します 外部 imgs 変数が受け取る値は未定義です すべての画像がローカル キャッシュを持つ場合にのみ、外部 imgs 変数はすべてのプリロードされた画像を正常に取得できます画像リソースの配列
1 つの画像をロードしてから次の画像をロードすると、画像のプリロード プロセス全体に比較的長い時間がかかり、ユーザー エクスペリエンスが低下し、元の非同期操作が特殊になります。この実装方法は、onload 非同期機能を完全に放棄するのと同じです。
複数画像のプリロード (改良版)
今回は、空の配列を直接配置します。がパラメータとして関数に渡され、すべての画像がこの配列に格納されます。以下は改良された関数コードです (jQuery を使用できると仮定しています)
function preloadImg(list,imgs) { var def = $.Deferred(), len = list.length; $(list).each(function(i,e) { var img = new Image(); img.src = e; if(img.complete) { imgs[i] = img; len--; if(len == 0) { def.resolve(); } } else { img.onload = (function(j) { return function() { imgs[j] = img len--; if(len == 0) { def.resolve(); } }; })(i); img.onerror = function() { len--; console.log('fail to load image'); }; } }); return def.promise(); } var list = [......], //此处省略一万个字符 imgs = []; $.when(preloadImg(list, imgs)).done( function() { //预加载结束 //do something here } );
onload コールバック関数を各 img に個別にバインドする場合クロージャを使用する目的は、現在のインクリメント変数 i を保存することです。これが行われない場合、ローカルにキャッシュされていないリスト アドレス内の画像が imgs
## の最後の要素に保存されることになります。 # 今回は画像がロードされるたびに、リスト配列から画像のアドレスを削除しないので、後でリスト配列のデータを使用する必要があるときに、正常に取得できます。このコードでは、jQuery の Deferred オブジェクトを導入しました。これにより、画像をプリロードするプロセス全体を簡単に把握できるようになります。以上がjQuery が画像のプリロード関数を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。