Сначала загрузите фоновое изображение с низким разрешением, затем с высоким разрешением

Я пытаюсь оптимизировать размер моего сайта, когда он выводится клиенту. Я до 1,9 МБ и 29 КБ при кешировании. Проблема в том, что первая загрузка содержит изображение, которое очень неоптимизировано для мобильных устройств; он имеет разрешение 1080p.

Итак, я ищу метод, который позволяет мне сначала загрузить версию с низким разрешением (min.bg.jpg), и как только сайт загрузится, используйте версию с высоким разрешением - или даже одну с разрешением, близким к устройству (NNNxNNN.bg.jpg или просто bg.jpg).

Фон устанавливается с использованием CSS точно так же, как ожидали все. Его применение к телу и всему заявлению выглядит следующим образом:

body {
    background: url("/cdn/theme/images/bg.jpg");
    color: white;
    height: 100%;
    width: 100%;
    background-repeat: no-repeat;
    background-position: 50% 50%;
    background-attachment: fixed;
}

Теперь я хочу изменить это, чтобы вместо min.bg.jpg использовать min.bg.jpg для первой загрузки, а затем что-то вроде этого:

jQuery(function(){
    jQuery("body").[...]
});

В каком порядке я буду асинхронно загружать новый фон, а затем вставлять его в качестве нового фонового изображения CSS?

Чтобы показать некоторые отличия, вот пример основной и мини-версии, которую я использую для тестирования:

[email protected] ~/Work/BIRD3/cdn/theme/images $ file *.jpg
bg.jpg:     JPEG image data, EXIF standard
min.bg.jpg: JPEG image data, JFIF standard 1.01
[email protected] ~/Work/BIRD3/cdn/theme/images $ du -h *.jpg
1,0M    bg.jpg
620K    min.bg.jpg

Ответы

Ответ 1

Здесь используется метод...

CSS

#div_whatever {
   position: whatever;
   background-repeat: no-repeat;
   background-position: whatever whatever; 
   background-image: url(dir/image.jpg);
   /* image.jpg is a low-resolution at 30% quality. */
}

#img_highQuality {
    display: none;
}

HTML:

<img id="img_highQuality" src="dir/image.png">
<!-- img.png is a full-resolution image. -->

<div id="div_whatever"></div>

Jquery:

$("#img_highQuality").off().on("load", function() {
    $("#div_whatever").css({
        "background-image" : "url(dir/image.png)"
    });
});
// Side note: I usually define CSS arrays because
// I inevitably want to go back and add another 
// property at some point.

Что происходит:

  • Быстро загружается низкоуровневая версия фона.
  • В то же время версия с более высоким разрешением загружается как скрытое изображение.
  • Когда загружается изображение с высоким разрешением, jQuery меняет изображение с низким разрешением div с версией с высоким разрешением.

PURE JS VERSION

Этот пример будет эффективным для изменения одного или нескольких элементов.

CSS

.hidden {
   display: none;
}

#div_whatever {
   position: whatever;
   background-repeat: no-repeat;
   background-position: whatever whatever; 
   background-image: url(dir/image.jpg);
   /* image.jpg is a low-resolution at 30% quality. */
}

HTML:

<div id="div_whatever"></div>
<img id="img_whatever" class="hidden" src="dir/image.png" onload="upgradeImage(this);">

JAVASCRIPT:

function upgradeImage(object) {
    var id = object.id;
    var target = "div_" + id.substring(4);

    document.getElementById(target).style.backgroundImage = "url(" + object.src + ")";
}

ОБНОВЛЕНИЕ/УЛУЧШЕНИЕ (1/31/2017)

Это усовершенствование вдохновлено gdbj отличным моментом, что мое решение приводит к тому, что путь изображения указан в трех местах. Хотя я не использовал метод gdbj addClass(), следующий код jQuery изменен, чтобы извлечь путь к изображению (а не быть связанным с кодом jQuery), Что еще более важно, эта версия допускает множественные замены изображений с высоким разрешением с высоким разрешением.

CSS

.img_highres {
  display: none;
}

#div_whatever1 {
  width: 100px;
  height: 100px;
  background-repeat: no-repeat;
  background-position: center center;
  background-image: url(PATH_TO_LOW_RES_PHOTO_1);
}

#div_whatever2 {
  width: 200px;
  height: 200px;
  background-repeat: no-repeat;
  background-position: center center;
  background-image: url(PATH_TO_LOW_RES_PHOTO_2);
}

HTML

<div id="div_whatever1"></div>
<img id="img_whatever1" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_1">

<div id="div_whatever2"></div>
<img id="img_whatever2" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_2">

JQuery

  $(function() {
      $(".img_highres").off().on("load", function() {
         var id = $(this).attr("id");
         var highres = $(this).attr("src").toString();
         var target = "#div_" + id.substring(4);
         $(target).css("background-image", "url(" + highres + ")");
      });
   });

Что происходит:

  • Изображения с низким разрешением загружаются для каждого из разделов на основе их CSS настройки фонового изображения. (Обратите внимание, что CSS также устанавливает div в размеры.)
  • Тем временем фотографии с более высоким разрешением загружаются как скрытые изображения (все используют имя класса img_highres).
  • Функция jQuery запускается каждый раз, когда фото img_highres завершает загрузку.
  • Функция jQuery считывает путь изображения src и изменяет фоновое изображение соответствующего div. в пример выше, соглашение об именах является "div_ [name]" для видимых divs и "img_ [то же имя]" для изображений с высоким разрешением, загруженных в фон.

Ответ 2

Попробуем простой:

<img border="0" 
     style="background:url(http://i.stack.imgur.com/zWfJ5.jpg) no-repeat; 
            width:1920px;
            height:1200px"
     src="http://i.stack.imgur.com/XOYra.jpg" width="1920" height="1200" />

zWfJ5.jpg - версия с низким разрешением, а XOYra.jpg - версия с высоким разрешением.

Если есть способ организовать загрузку, поэтому сначала отображается фоновое изображение, это может быть самым простым, о котором я могу думать.

где низкое разрешение 44k: низкое разрешение 44k:

а высокое разрешение - 1,16 М высокое разрешение - 1,16M

результат:

jsFiddled здесь (для загрузки сравнения требуется большее изображение.)

Ответ 3

Немного поздно, но вы можете использовать это чрезвычайно простое решение: вы можете поместить два изображения в фоновом режиме css:

  background-image: url("high-res.jpg"),url("low-res.jpg");

Браузер отобразит изображение с низким разрешением, а затем отобразит высокое разрешение по сравнению с низким разрешением, когда оно будет загружено.

Ответ 4

Я бы обычно оптимизировал изображение с помощью Grunt или онлайн-инструмента, такого как Tiny PNG, чтобы уменьшить размер файла.

Затем вы можете отложить загрузку изображений, я нашел следующую статью полезной, когда дело доходило до отсрочки изображений - https://www.feedthebot.com/pagespeed/defer-images.html

В статье обсуждается использование изображения base64 для начальной загрузки, а затем откладывается загрузка изображения высокого качества. Значок изображения, упомянутый в статье, выглядит следующим образом.

<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">

JavaScript, упомянутый в статье, выглядит следующим образом:

<script type="text/javascript" async>
function init() {
    var imgDefer = document.getElementsByTagName('img');
    for (var i=0; i<imgDefer.length; i++) {
        if(imgDefer[i].getAttribute('data-src')) {
            imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
        }
    }
}
window.onload = init;
</script>

Надеюсь, это поможет.

Ответ 5

Все ответы, приведенные выше, в основном работают с небольшой корректировкой, но вот способ, который я считаю коротким и простым, чтобы начать.

Замечания:

  • Раскомментируйте код, загрузите изображение с высоким разрешением для использования, функция сна просто для имитации медленной сети.
  • На самом деле, этот метод не загружает 2 ресурса (низкий и высокий) одновременно, но он приемлем, потому что низкий ресурс не займет много времени для загрузки.
  • Просто скопируйте весь код и запустите для быстрой проверки.

<!DOCTYPE html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>

    <style type="text/css">
      
    </style>
  </head>

  <body>
    <!-- Load low res image first -->
    <img style="width: 400px; height: auto;" alt="" src="https://s3-ap-southeast-1.amazonaws.com/wheredat/banner-low-quality/banner_20180725_123048.jpg" onload="upgrade(this)">
  </body>
  
  <script type="text/javascript">

	function upgrade(image){

                // After load low res image, remove onload listener.

		// Remove onload listener.
		$(image).prop("onload", null);

                // Load high resolution image.
                // $(image).attr('src', 'https://s3-ap-southeast-1.amazonaws.com/wheredat/banner/banner_20180725_123048.jpeg');

		// Simulate slow network, after 1.5s, the high res image loads.
		sleep(1500).then(() => {
		    // Do something after the sleep!

			// Load a high resolution image.
			$(image).attr('src', 'https://s3-ap-southeast-1.amazonaws.com/wheredat/banner/banner_20180725_123048.jpeg');
		});	
	}

	// Sleep time expects milliseconds
	function sleep (time) {
	  return new Promise((resolve) => setTimeout(resolve, time));
	}

  </script>
  
</html>

Ответ 6

В Ubuntu/Chrome 71 ответ Milche не работает для меня согласованно, и изображение с более высоким разрешением (через img src) часто загружается и разрешается до того, как изображение с более низким разрешением (через background CSS) даже начинает загружаться.

Мое решение начать с более низким разрешением изображения в качестве src и использовать Image класса для создания незакрепленного <img> экземпляра с высоким разрешением изображения. После загрузки обновите существующий источник <img> источником изображения с высоким разрешением.

HTML:

<img id='my-image' src='low-res.png' alt='Title' width='1920px' height='1200px'>

JavaScript:

window.addEventListener('load', function() {
    loadHighResImage(document.getElementById('my-image'), 'high-res.png')
})

function loadHighResImage(elem, highResUrl) {
    let image = new Image()
    image.addEventListener('load', () => elem.src = highResUrl)
    image.src = highResUrl
}

Скрипка: https://jsfiddle.net/25aqmd67/

Этот подход работает для изображений с низким разрешением, которые также просто уменьшаются.

Ответ 7

Вы пробовали использовать спрайты CSS, чтобы помочь получить то, что вы хотите? http://css-tricks.com/css-sprites/