簡體   English   中英

從緩存數組中檢索預加載的圖像

[英]Retrieve preloaded image from cached array

我正在使用JavaScript進行多個圖像預加載,並且為每個圖像都分配了一些樣式屬性,這是可能的,因為它們是HTML Images元素。 我用的是無極的技術,我發現這里 StackOverflow上:

function preloadImages(srcs) {
  function loadImage(imgToLoad) {
    return new Promise(function(resolve, reject) {
        var img = new Image();
        img.onload = function() {
            resolve(img);
        };
        img.onerror = img.onabort = function() {
            reject(imgToLoad.src);
        };
        img.className = 'testimg'; //Test to see if I can retrieve img
        img.src = imgToLoad.src;
        img.style.top = imgToLoad.top;
    });
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
    promises.push(loadImage(srcs[i]));
}
return Promise.all(promises);
}

“ srcs”值的示例:

srcs[0].top = '15%';
srcs[0].src = 'img/myImage1.jpg';
srcs[1].top = '24%';
srcs[1].src = 'img/myImage2.jpg';

預加載部分工作完美,並且在流程結束時我能夠獲得所有預加載的圖像,看到樣式屬性已被應用,如下所示:

preloadImages(imgToLoad).then(function(imgs) {
    // all images are loaded now and in the array imgs
    console.log(imgs); // This works
    console.log(document.getElementsByClassName('testimg')); //This doesn't
}, function(errImg) {
    // at least one image failed to load
    console.log('error in loading images.');
});

但是,在我的代碼后面,我想從預加載的圖像數組中提取一些元素,因此我可以追加它們而不必精確調整樣式屬性。

我的意思是,不僅限於.append('aSrcThatHasBeenPreloaded'); 我想保留在預加載期間定義的類和樣式屬性。

那有可能嗎? 如果是這樣,我應該如何進行?

我嘗試了document.getElementsByClassName('myPreloadedClass')但是它返回一個空結果,這意味着預加載的圖像不是DOM的一部分(這很有意義)。

謝謝您的幫助。

您將必須確保可以某種方式檢索預加載的img元素。 有很多方法可以做到這一點,但是馬上想到了三種。

1.在DOM中添加了加載的圖片

在您的示例中,您嘗試使用查詢選擇器檢索圖像。 失敗是因為img元素未添加到DOM。 您可以將它們附加到對用戶隱藏的DOM元素上。

 var images = [ { src: '//placehold.it/550x250?text=A', top: 0, class:'img-a' // unique class name to retrieve item using a query selector. }, { src: '//placehold.it/550x250?text=B', top: 0, class:'img-b' }], imageCache = document.getElementById('image-cache'); function preloadImages(srcs) { function loadImage(imgToLoad) { return new Promise(function(resolve, reject) { var img = new Image(); img.onload = function() { // The image has been loaded, add it to the cache element. imageCache.appendChild(img); resolve(img); }; img.onerror = img.onabort = function() { reject(imgToLoad.src); }; img.className = 'testimg ' + imgToLoad.class; //Test to see if I can retrieve img img.src = imgToLoad.src; img.style.top = imgToLoad.top; }); } var promises = []; for (var i = 0; i < srcs.length; i++) { promises.push(loadImage(srcs[i])); } return Promise.all(promises); } // Load all the images. preloadImages(images) .then(result => { // Add img B from the cache to the proof div. document.getElementById('proof').appendChild(imageCache.querySelector('.img-b')); }); 
 .hidden { display: none; } 
 <div id="image-cache" class="hidden"></div> <div id="proof"></div> 

2.將加載的圖像添加到文檔片段

如果您不想將img添加到DOM中,則可以將它們添加到文檔片段中 這樣,網站的訪問者將無法輕松訪問它們,並且您仍然可以使用查詢選擇器來檢索圖像。

 var images = [ { src: '//placehold.it/550x250?text=A', top: 0, class:'img-a' // unique class name to retrieve item using a query selector. }, { src: '//placehold.it/550x250?text=B', top: 0, class:'img-b' }], // Create a document fragment to keep the images in. imageCache = document.createDocumentFragment();; function preloadImages(srcs) { function loadImage(imgToLoad) { return new Promise(function(resolve, reject) { var img = new Image(); img.onload = function() { // The image has been loaded, add it to the cache element. imageCache.appendChild(img); resolve(img); }; img.onerror = img.onabort = function() { reject(imgToLoad.src); }; img.className = 'testimg ' + imgToLoad.class; //Test to see if I can retrieve img img.src = imgToLoad.src; img.style.top = imgToLoad.top; }); } var promises = []; for (var i = 0; i < srcs.length; i++) { promises.push(loadImage(srcs[i])); } return Promise.all(promises); } // Load all the images. preloadImages(images) .then(result => { // Add img B from the cache to the proof div. document.getElementById('proof').appendChild(imageCache.querySelector('.img-b')); // And try to add img B from the cache to the proof2 div. The image will only be visible once in the site. document.getElementById('proof2').appendChild(imageCache.querySelector('.img-b')); }); 
 .hidden { display: none; } 
 <div id="proof"></div> <div id="proof2" style="margin-top:1em"></div> 

不足之處

第二種解決方案與第一種解決方案非常相似。 您仍然可以使用查詢選擇器來訪問圖像。 但是,這兩種解決方案都有相同的缺點,一旦您將緩存中的圖像放置在站點上的其他任何地方,您就無法再從緩存中檢索圖像。 這是因為一個元素只能在DOM中出現一次,並將其附加到另一個元素會將其從其先前的父元素中刪除。

3.一段可重用的代碼

我建議創建一個閉包或ES6類,在其中可以放置用於預加載圖像和檢索圖像的所有功能。

以下代碼段的關閉返回了兩種方法:

  1. preloadImages ,它需要預加載圖像數組。
  2. getImage ,它帶有一個有效的CSS選擇器,該選擇器用於從文檔片段中檢索所需的img元素。 在返回該元素之前,它將對其進行克隆,因此您可以向DOM中多次添加相同的預加載圖像。

克隆一個元素也將克隆它的ID,這一點要注意。 我認為這不是什么大問題,因為img是用代碼創建的,因此您可以完全控制它。

我使用文檔片段來存儲預加載的圖像,因為我認為這是比將圖像添加到DOM更優雅的解決方案。 如果不使用getImage方法,則獲取img元素會變得更加困難,從而防止以某種方式從圖像緩存中刪除預加載的img元素。

 var images = [ { src: '//placehold.it/550x250?text=A', top: 0, class:'img-a' // unique class name to retrieve item using a query selector. }, { src: '//placehold.it/550x250?text=B', top: 0, class:'img-b' }]; var imagesPreloader = (function() { var imagesCache = document.createDocumentFragment(); function loadImage(imgToLoad) { return new Promise(function(resolve, reject) { var img = new Image(); img.onload = function() { imagesCache.appendChild(img) resolve(); }; img.onerror = img.onabort = function() { reject(imgToLoad.src); }; img.className = 'testimg ' + imgToLoad.class ; //Test to see if I can retrieve img img.src = imgToLoad.src; img.style.top = imgToLoad.top; }); } function preloadImages(srcs) { var promises = []; for (var i = 0; i < srcs.length; i++) { promises.push(loadImage(srcs[i])); } return Promise.all(promises); } function getImage(imageSelector) { const // Find the image in the fragment imgElement = imagesCache.querySelector(imageSelector); // When the selector didn't yield an image, return null. if (imgElement === null) { return null; } // Clone the image element and return it. const resultElement = imgElement.cloneNode(); return resultElement; } return { getImage, preloadImages }; })(); imagesPreloader.preloadImages(images) .then(result => { console.log('Image with class "img-a": ', imagesPreloader.getImage('.img-a')); document.querySelector('#proof').appendChild(imagesPreloader.getImage('.img-b')); document.querySelector('#proof2').appendChild(imagesPreloader.getImage('.img-b')); }); 
 <div id="proof"></div> <div id="proof2" style="margin-top:1em"></div> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM