Как предварительно загрузить изображение с помощью JS [duplicate]

tl; dr: реализует Runnable лучше. Тем не менее, оговорка важна

. В общем, я бы рекомендовал использовать что-то вроде Runnable, а не Thread, потому что это позволяет вам поддерживать вашу работу только в сочетании с вашим выбором параллелизма. Например, если вы используете Runnable и позже решили, что на самом деле этого не требуется Thread, вы можете просто вызвать threadA.run ().

Предостережение: здесь, Я категорически отвергаю использование необработанных потоков. Я предпочитаю использовать Callables и FutureTasks (Из javadoc: «Адаптивное асинхронное вычисление»). Интеграция тайм-аутов, правильная отмена и объединение потоков современной поддержки параллелизма для меня гораздо более полезны, чем груды необработанных потоков.

Последующие действия: существует конструктор FutureTask , который позволяет использовать Runnables (если это то, что вам больше всего нравится), и по-прежнему пользоваться преимуществами современных инструментов параллелизма. Процитировать javadoc:

Если вам не нужен конкретный результат, подумайте об использовании конструкций формы:

Future f = new FutureTask(runnable, null)

Итак, если мы заменим их runnable на ваш threadA, мы получаем следующее:

new FutureTask(threadA, null)

Другим вариантом, который позволяет вам оставаться ближе к Runnables, является ThreadPoolExecutor . Вы можете использовать метод execute для передачи в Runnable для выполнения «данной задачи в будущем».

Если вы хотите попробовать использовать пул потоков, вышеописанный фрагмент кода будет выглядеть примерно следующим образом (с использованием фабричного метода Executors.newCachedThreadPool () ):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

180
задан Alexis Wilke 9 August 2016 в 23:12
поделиться

8 ответов

Да. Это должно работать на всех основных браузерах.

89
ответ дан Alex M. 18 August 2018 в 19:38
поделиться

В моем случае было полезно добавить обратный вызов вашей функции для события 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.src = url;
      img.onload = anImageLoadedCallback;
  }
}

// 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');
});
9
ответ дан Alexander 18 August 2018 в 19:38
поделиться

Попробуйте это, я думаю, что это лучше.

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/

35
ответ дан clintgh 18 August 2018 в 19:38
поделиться
  • 1
    аккуратный и аккуратный! – JackDev 7 April 2015 в 16:18
  • 2
    нет обработчика onload для любого изображения – Benny Schmidt 27 July 2015 в 18:22
  • 3
  • 4
    @BeNice Я думаю, что вы недопонимаете, загрузка изображений - асинхронная, поэтому вы должны обрабатывать состояние onload или просто создавать изображения в памяти. – Benny Schmidt 31 March 2016 в 15:35
  • 5
    Если вы используете это решение, не забывайте оператор var для i-переменной. В противном случае он будет установлен глобально, что может вызвать ошибку, которую действительно трудно решить (если вы не знаете, что вы забыли оператор var. for (var i = 0..... – Mohammer 13 June 2016 в 23:37
  • 6
    @Mohammer спасибо за это, я просто скопировал код из ссылки, которую я предоставил. Теперь я отредактирую код, чтобы добавить var – clintgh 14 June 2016 в 02:55

Я рекомендую использовать 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, поэтому избегайте его вообще ИМХО вопреки вкладу Свобоева. Image () имеет лучшую поддержку в старых браузерах.

10
ответ дан Dave 18 August 2018 в 19:38
поделиться
  • 1
    Я не думаю, что это то, как вы ломаете ошибки при загрузке Image в javascript - есть что-то вроде _img.onerror, который может (должен?) Использоваться. – Greg0ry 23 September 2015 в 08:57
  • 2
    Что такое «возможные проблемы»? – Kissaki 25 April 2017 в 16:37
  • 3
    Такие вопросы, как поддержка команды. Проверьте сайт и «могу ли я использовать»? чтобы узнать, поддерживает ли браузер, который требуется для поддержки, поддержка команды javascript. – Dave 26 January 2018 в 15:44

Этот подход немного более сложный. Здесь вы сохраняете все предварительно загруженные изображения в контейнере, может быть 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;
}

Попробуйте здесь , я также добавил несколько комментариев

9
ответ дан freedev 18 August 2018 в 19:38
поделиться
  • 1
    Должно быть прокомментировано – freedev 31 January 2016 в 14:35
  • 2
    Опять же, пожалуйста, я действительно забочусь о своем ответе. Прошу прокомментировать ваши голоса, чтобы я мог улучшить свой ответ. – freedev 9 August 2017 в 02:10
  • 3
    Я думаю, что downvotes - это то, что вы обращаетесь к dom при вызове функции, что может быть проблематичным, если у вас есть другая функция, обращающаяся к dom, чтобы найти элемент одновременно. – user 12 February 2018 в 17:01
  • 4
    Спасибо @Programmer, я понял. Во всяком случае, основная идея этого примера состоит в том, что элемент должен отображаться только при успешной загрузке. В этом случае я реорганизую код, запускающий функцию обратного вызова. – freedev 13 February 2018 в 17:48

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)

.preload-images {
  display: none; 
  width: 0;
  height: 0;
  background: url(img01.jpg),
              url(img02.jpg),
              url(img03.jpg);
}

ПРИМЕЧАНИЕ. Изображения в контейнере с display:none могут не предустановить , Возможно, видимость: скрытые будут работать лучше, но я не проверял это. Спасибо Marco Del Valle за указание на это

20
ответ дан mplungjan 18 August 2018 в 19:38
поделиться
  • 1
    Спасибо mplungjan. Хотя это не помогает мне в этом конкретном случае, это хорошо знать. – Francisc 6 September 2010 в 10:36
  • 2
    Правильно ли я говорю, что это замедлит загрузку страницы, потому что эти изображения нужно загрузить до того, как страница может запустить событие загрузки? – Jakub 7 March 2015 в 18:23
  • 3
    Я не верю, что они будут работать во всех браузерах. Я знаю, что на изображениях Chrome не загружаются, пока они не будут видны. Вам нужно будет удалить дисплей: none; и вместо этого попытайтесь расположить их, чтобы их не видно. Затем можно скрыть JS после того, как все загрузится, если потребуется. – Bullyen 29 December 2015 в 17:02
  • 4
    Фоновые изображения в элементе с display: none не будут предварительно загружены. – Marquizzo 17 March 2016 в 22:44
  • 5
    Этот метод работал для меня, только я (1) не использовал display: none, (2) не использовал width/height: 0, (3) put no-repeat и такую ​​позицию, чтобы изображение было снаружи (-<width>px -<height>px вы получите там, поэтому, если ваши изображения имеют 100px по высоте или меньше, вы можете использовать 0 -100px, другими словами url(...) no-repeat 0 -100px. – Alexis Wilke 10 August 2016 в 00:37

Вот мой подход:

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);
    }
};
1
ответ дан naeluh 18 August 2018 в 19:38
поделиться

Да, это сработает, однако браузеры будут ограничивать (между 4-8) фактические вызовы и, таким образом, не кэшировать / предварительно загружать все нужные изображения.

Лучшим способом сделать это является вызов 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;
}
3
ответ дан Robin 18 August 2018 в 19:38
поделиться
  • 1
    Не могли бы вы связать некоторую ссылку об этом листе браузеров? – nulll 10 July 2016 в 08:26
  • 2
    Трудно найти ссылку (по крайней мере, я ее никогда не обнаружил), но я использовал свой собственный проект, чтобы проверить это, внимательно изучая то, что было загружено из кеш-серверов и вызовов сервера, используя вкладку сети Chrome в инструментах разработчика Chrome (f12). Я нашел такое же поведение в Firefox и с помощью мобильных устройств. – Robin 6 December 2016 в 05:22
Другие вопросы по тегам:

Похожие вопросы: