जावास्क्रिप्ट के साथ छवियों को लोड करना


263

क्या फ़ंक्शन मैंने सबसे नीचे छवियों को प्रीलोड करने के लिए पर्याप्त लिखा है, यदि सभी नहीं, तो आमतौर पर आज उपयोग किए जाने वाले ब्राउज़र?

function preloadImage(url)
{
    var img=new Image();
    img.src=url;
}

मेरे पास छवि URL की एक सरणी है जिसे मैं लूप करता हूं और preloadImageप्रत्येक URL के लिए फ़ंक्शन को कॉल करता हूं ।


19
ध्यान दें कि कुछ (सभी?) ब्राउज़र कुछ सेकंड के बाद छवि जारी करेंगे यदि आपने इसका उपयोग नहीं किया है। इससे बचने के लिए, imgऑब्जेक्ट को संदर्भ में रखें , उदाहरण के लिए पैरेंट स्कोप में एक सरणी में।
तमलिन

3
"छवि जारी करें" से आपका क्या अभिप्राय है? यदि यह ब्राउज़र द्वारा कैश किया गया था, तो यह वहीं रहेगा, है ना?
फ्रांसिस

56
थोड़ा छोटा:(new Image()).src = url;
mrzmyr

20
ध्यान दें कि जब क्रोम devtool खुला हो तो यह काम नहीं करेगा और नेटवर्क पैनल के भीतर 'अक्षम चच' सक्षम है
Wayou

6
इससे भी छोटा:new Image().src = url;
डैनियल एक्स मूर

जवाबों:


163

हाँ। यह सभी प्रमुख ब्राउज़रों पर काम करना चाहिए।


48
मॉडरेटर नोट: कृपया इसे "एक उत्तर नहीं" के रूप में चिह्नित करना बंद करें। यह वास्तव में, उस प्रश्न का सीधा उत्तर है जो पूछा गया था। यदि आपको लगता है कि उत्तर गलत है, या अपर्याप्त रूप से साक्ष्य के साथ समर्थित है, तो इसे डाउनवोट करें
कोड़ी ग्रे

43

मुझे लगता है कि यह बेहतर है की कोशिश करो।

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/


3
onloadकिसी भी चित्र के लिए कोई हैंडलर नहीं है
Benn

12
क्या आप बता सकते हैं कि यह बेहतर क्यों है?
जेजे

2
@BeNice मुझे लगता है कि आप गलत समझ रहे हैं, छवियों को लोड करना async है, इसलिए आपको onloadस्थिति को संभालना होगा या आप केवल मेमोरी में छवियों को इंस्टेंट कर रहे हैं ।
बेनी

3
यदि आप इस समाधान का उपयोग करते हैं, तो आई-चर के लिए var स्टेटमेंट को न भूलें। अन्यथा यह विश्व स्तर पर सेट किया जाएगा जो त्रुटि का कारण बन सकता है जो वास्तव में हल करना मुश्किल है (जब तक कि आप यह नहीं जानते कि आप for (var i = 0.....
वार्

2
@ इसके लिए धन्यवाद, मैंने अभी दिए लिंक से कोड कॉपी किया। मैं अब कोड को संपादित var
करूँगा

26

मेरे मामले में 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');
});

19

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प्रीलोड नहीं हो सकती हैं। शायद दृश्यता: छिपी बेहतर काम करेगी लेकिन मैंने इसका परीक्षण नहीं किया है। शुक्रिया मार्को डेल वैले इसे इंगित करने के लिए


धन्यवाद mplungjan हालांकि यह इस विशेष मामले में मेरी मदद नहीं करता है, यह जानना अच्छा है।
फ्रांसिस

5
क्या मैं सही कह रहा हूं कि इससे पृष्ठ का लोड धीमा हो जाएगा क्योंकि लोड घटना को लॉन्च करने से पहले इन छवियों को डाउनलोड करने की आवश्यकता है?
जकुबिसज़ोन

3
मुझे विश्वास नहीं है कि ये सभी ब्राउज़रों पर काम करेंगे। मुझे पता है कि क्रोम छवियों को तब तक लोड नहीं किया जाता है जब तक वे दिखाई नहीं देते हैं। प्रदर्शन को हटाने की आवश्यकता होगी: कोई नहीं; और इसके बजाय उन्हें देखने की कोशिश करें और उन्हें स्थिति दें। जरूरत पड़ने पर सबकुछ लोड होने के बाद जेएस के साथ छुपा सकते हैं।
बुल्लेयन

3
एक तत्व के साथ पृष्ठभूमि चित्र display: noneप्रीलोड नहीं होंगे।
Marquizzo

1
इस विधि ने मेरे लिए केवल I (1) का उपयोग नहीं किया display: none, (2) ने width/height: 0(3) पुट का उपयोग नहीं किया no-repeatऔर एक स्थिति ऐसी है कि छवि बाहर -<width>px -<height>pxहोगी ( आपको वहां मिलेगी, इसलिए यदि आपकी छवियाँ सभी 100px में हैं ऊँचाई या कम, आप 0 -100pxदूसरे शब्दों में उपयोग कर सकते हैं url(...) no-repeat 0 -100px
एलेक्सिस विल्के

11

मैं आपको कुछ संभावित मुद्दों को रोकने के लिए एक कोशिश / पकड़ का उपयोग करने की सलाह देता हूं:

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 का उपयोग करने में आपके साथ समस्या हो सकती है, इसलिए इसे फ्रीडम के योगदान के विपरीत IMHO से बचें। पुराने कचरा ब्राउज़रों में छवि () का बेहतर समर्थन है।


7
मुझे नहीं लगता कि यह है कि आप जावास्क्रिप्ट में छवि लोड करते समय त्रुटियों को कैसे पकड़ते हैं - _img.onerror जैसी कुछ चीज है जो (चाहिए?) का उपयोग किया जाना चाहिए।
ग्रेग्री

3
"संभावित मुद्दे" क्या हैं?
Kissaki

कमांड के लिए समर्थन जैसे मुद्दे। साइट देखें "मैं उपयोग कर सकता हूं" यह देखने के लिए कि क्या आपको जिस ब्राउज़र का समर्थन करना है, उसके पास जावास्क्रिप्ट कमांड के लिए समर्थन है।
डेव

10

यह दृष्टिकोण थोड़ा अधिक विस्तृत है। यहां आप सभी प्रीलोड किए गए चित्रों को एक कंटेनर में संग्रहीत करते हैं, एक 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;
}

इसे यहाँ आज़माएँ , मैंने कुछ टिप्पणियाँ भी जोड़ दी हैं


7
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)))

5

हां यह काम करेगा, हालांकि ब्राउज़र सीमित हो जाएंगे वास्तविक कॉल (और 4-8 के बीच) और इस तरह सभी वांछित छवियों को कैश / प्रीलोड नहीं करेगा।

ऐसा करने का एक बेहतर तरीका यह है कि इस तरह की छवि का उपयोग करने से पहले ऑनलोड को कॉल करें:

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;
}

क्या आप इस ब्राउज़र सीमा के बारे में कुछ संदर्भ जोड़ सकते हैं?
nulll

एक संदर्भ ढूंढना कठिन है (कम से कम मुझे कभी नहीं मिला), लेकिन मैंने क्रोम डेवलपर टूल (f12) में Chrome के नेटवर्क टैब का उपयोग करके कैश और सर्वर कॉल से लोड होने पर निकटता से देखने के लिए अपने स्वयं के प्रोजेक्ट का उपयोग किया। मुझे फ़ायरफ़ॉक्स और मोबाइल का उपयोग करने में समान व्यवहार मिला।
रोबिन

1
-1 क्योंकि मैंने यहां पहले वाक्य में दावे का ध्यानपूर्वक परीक्षण किया और पाया कि यह गलत है, कम से कम आधुनिक ब्राउज़रों में। देखें stackoverflow.com/a/56012084/1709587 हां, समानांतर HTTP अनुरोधों की अधिकतम संख्या पर एक सीमा है जो ब्राउज़र भेजने के लिए तैयार है, लेकिन यह अंततः उस प्रत्येक URL का अनुरोध करने के लिए गोल हो जाता है, जिस पर आप प्री लोड करते हैं, भले ही आप इसे प्रश्न में दिखाए गए तरीके से करते हों।
मार्क एमी

5

यहाँ मेरा दृष्टिकोण है:

var preloadImages = function (srcs, imgs, callback) {
    var img;
    var remaining = srcs.length;
    for (var i = 0; i < srcs.length; i++) {
        img = new Image;
        img.onload = function () {
            --remaining;
            if (remaining <= 0) {
                callback();
            }
        };
        img.src = srcs[i];
        imgs.push(img);
    }
};

4

ECMAScript 2017 के अनुरूप ब्राउज़रों के लिए समाधान

ध्यान दें: यह भी काम करेगा यदि आप बैबेल जैसे ट्रांसपिलर का उपयोग कर रहे हैं।

'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);
}

वादों के बारे में अधिक

"Async" फ़ंक्शन के बारे में अधिक

विनाशकारी असाइनमेंट के बारे में अधिक

ECMAScript 2015 के बारे में अधिक

ECMAScript 2017 के बारे में अधिक


2

मैं इस बात की पुष्टि कर सकता हूँ कि प्रश्न में दृष्टिकोण, डाउनलोड और कैश्ड होने के लिए छवियों को ट्रिगर करने के लिए पर्याप्त है (जब तक कि आपने ब्राउज़र को अपनी प्रतिक्रिया हेडर के माध्यम से ऐसा करने से मना नहीं किया है), कम से कम:

  • क्रोम 74
  • सफ़ारी १२
  • फ़ायरफ़ॉक्स 66
  • धार १ 17

इसका परीक्षण करने के लिए, मैंने कई एंडपॉइंट्स के साथ एक छोटा सा वेबैप बनाया, जिसमें प्रत्येक एक बिल्ली के बच्चे की तस्वीर परोसने से पहले 10 सेकंड के लिए सोता था। फिर मैंने दो वेबपृष्ठ जोड़े, जिनमें से एक में एक <script>टैग था जिसमें प्रत्येक बिल्ली के बच्चे को preloadImageसवाल से फ़ंक्शन का उपयोग करके पहले से लोड किया गया था, और दूसरे में <img>टैग का उपयोग करके पृष्ठ पर सभी बिल्ली के बच्चे शामिल हैं ।

उपरोक्त सभी ब्राउज़रों में, मैंने पाया कि अगर मैंने पहले प्रीलोडर पेज पर जाकर देखा, तो थोड़ी देर इंतजार किया, और फिर <img>टैग के साथ पेज पर गया , मेरे बिल्ली के बच्चे तुरंत प्रस्तुत हुए। यह दर्शाता है कि प्रीलोडर ने परीक्षण किए गए सभी ब्राउज़रों में बिल्ली के बच्चे को सफलतापूर्वक कैश में लोड किया है।

आप https://github.com/ExplodingCabbage/preloadImage-test पर इसका परीक्षण करने के लिए मेरे द्वारा उपयोग किए गए एप्लिकेशन को देख या आज़मा सकते हैं ।

विशेष रूप से ध्यान दें कि यह तकनीक ऊपर के ब्राउज़रों में काम करती है, भले ही लूप की जा रही छवियों की संख्या समानांतर अनुरोधों की संख्या से अधिक हो जो रॉबिन के उत्तर से पता चलता है कि इसके विपरीत, ब्राउज़र एक समय में बनाने के लिए तैयार है। जिस दर पर आपकी छवियों प्रीलोड के पाठ्यक्रम कितने समानांतर द्वारा सीमित हो जाएगा का अनुरोध करता है ब्राउज़र को भेजने के लिए तैयार है, लेकिन यह होगा अंततः प्रत्येक चित्र URL आप कॉल का अनुरोध preloadImage()पर।


क्या यह मायने रखता है कि क्या चित्र मेमोरी या डिस्क में कैश्ड हैं? ऐसा लगता है कि ओपी विधि डिस्क पर कैश की गई है, जो @clintgh पद्धति के विपरीत है जो मेमोरी में कैश हो जाती है।
क्रिस एल

1

आप इस कोड को किसी भी यूआरएल से प्रीलोड छवियों के लिए index.html में स्थानांतरित कर सकते हैं

<link rel="preload" href="https://via.placeholder.com/160" as="image">

0

सिर में लिंक टैग का उपयोग करके ब्राउज़र सबसे अच्छा काम करेगा।

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);
    });
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.