Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   jQuery Image Loading (https://javascript.ru/forum/jquery/69209-jquery-image-loading.html)

Kyjek 06.06.2017 09:33

jQuery Image Loading
 
Доброго времени суток дорогие разработчики.
Пытаюсь создать слайдер. Идея заключается в том, чтобы картинки, используемые в слайдере, загружались не сразу, а только перед их запросом на отображение.
Контейнер для картинки имеет следующий вид:
<div class="slide" id="img1" data-img="img/slide-img/img (0).jpg"></div>

id="img1" - используется только для примера.
data-img="img/slide-img/img (0).jpg" - url изображения
для загрузки мне необходимо отловить события:
1. Загрузки (поместить в div индикатор загрузки )
<i class="fa fa-spinner fa-spin fa-2x" style="display:block;" aria-hidden="true"></i>

2. Ошибки (поместить в div индикатор ошибки )
<i class="fa fa-exclamation-triangle fa-2x" style="display:block;" aria-hidden="true"></i>

3. Готово (Все загрузилось, поместить загруженную картинку в div)
$('#img1').append(image);

Для примера возьмем событие для загрузки: «нажатие на блок».
Добавим обработчик в документ реаду
$('#img1').click(function () {
        var url = $('#img1').data('img');
        $.when(load_img_async(url)).done(function (image)
        {
            $('#img1').append(image);
        });
    });

Вытащим url и подставим его в функцию load_img_async, дождемся когда она выполнится. После чего запихнем картинку в div как написано в пункте 3.
Код функции
function load_img_async(source) {
    return $.Deferred(function (task) {
        var image = new Image();
        image.onload = function ()
        {
            $('#img1').empty();
            task.resolve(image);
        }
        image.onerror = function ()
        {
            $('#img1').empty().append('<i class="fa fa-exclamation-triangle fa-2x" style="display:block;" aria-hidden="true"></i>');
            task.reject();
        }
        $('#img1').empty().append('<i class="fa fa-spinner fa-spin fa-2x" style="display:block;" aria-hidden="true"></i>');
        image.src = source;
        image.className = "slide-img";
    }).promise();
}

Функция создает объект image и вешает два обработчика событий оnload все загружено и onerror ошибка. Далее наш div чистим и помещаем в него fa-spinner. Если ошибка то div чистим и помещаем в него fa-exclamation. Если же оnload все загружено то чистим div и возвращаем готовое изображение, которое будет помещено в этот же div.
Вроде все хорошо и работает, но я беру большую картинку (40мб). И вставляю ее. Загрузка происходит быстро ( ведь лежит в той же папке), но вот ее отрисовка происходит полосками. Предполагаю что $('#img1').append(image); кидает ее в контейнер и да она загружена, но не отрисованна и медленно появляется в контейнере.
Как отловить время отрисовки?
P.s. хотелось бы еще реализовать плавную смену индикатора загрузки, ошибки и картинки в diю
Моя маленькая прихоть получить % или kb загрузки картинки.
Готов рассмотреть другой подход к загрузке изображений. Спасибо всем кто откликнется!

Rise 06.06.2017 11:27

Цитата:

Сообщение от Kyjek (Сообщение 454630)
Как отловить время отрисовки?

Насколько мне известно специальных событий для этого нет, но есть такой трюк, выглядит правдоподобно)

Kyjek 06.06.2017 13:21

Спасибо.
Пример http://jsfiddle.net/4fg3K/34/ не работает как надо. Он так же как и мой код пропускает отрисовку.
function checkIfRendered(img, onRender) {
    var elRatio = img.width() / img.height();
    var natRatio = img.naturalWidth / img.naturalHeight;

    if (elRatio === natRatio)
        onRender();
    else {
        setTimeout(function() {
            checkIfRendered(img, onRender)
        }, 20);
    }
}

img.onload(checkIfRendered(img, function() { alert('rendered!'); }));

Вообще крашится на получении ширины экрана. Я если честно даже не понимаю почему.
Но люди же как то получают рисуют % загрузки фото, как это сделать?

Rise 06.06.2017 13:57

Цитата:

Сообщение от Kyjek (Сообщение 454651)
Но люди же как то получают рисуют % загрузки фото

А при чем здесь загрузка, если мы говорим про отрисовку?

Kyjek 06.06.2017 13:59

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

Но Вы правы эток делу не относится.

Rise 06.06.2017 14:14

Цитата:

Сообщение от Kyjek (Сообщение 454654)
и картинки показываются только после полной отрисовки.

Тоже 40мб? Или ты не видишь связи между весом картинки и скоростью отрисовки?

Kyjek 06.06.2017 14:30

Я вижу связь. Что картинка уже вся загрузилась и я теряю над ней всяческий контроль. событие onload произошло и все весь js считает что картинка загрузилась. То что она долго отрисовывается на экране это уже не проблема сети браузера и т.д. это полностью клиенская задача. Маленькие картинки не имеют таких проблем, да и использовать я буду восновном их, не более 100-400KB.
Что касается сторонних то например в lazyload картинка не отображается пока полностью не отрисуется, в дурацких так же как и у меня вылезает по строчкам.
Возможно стронние скрипты имеют более сложный функционал. За счет чего они этого добиваются.

Kyjek 06.06.2017 14:33

Работает как надо на ура
<img class="lazy" data-original="img/1.jpg" style="width:100%;" >
  <script src="jquery-2.2.4.js"></script>
  <script src="jquery.lazyload.js?v=1.9.1"></script>
  <script type="text/javascript" charset="utf-8">
  $(function() {
      $("img.lazy").lazyload();
  });
  </script>

Rise 06.06.2017 15:04

Kyjek, что работает, а где коллбэк по аналогии с предыдущим примером, или ты на глаз определил клоун?

Kyjek 06.06.2017 15:07

https://jsfiddle.net/Kyjek/ut4xmk56/1/

Да на глаз. При больших обьемах это видно. Открытого Коллбэка нет поэтому меня и не устраивает этот скрипт.


Часовой пояс GMT +3, время: 00:07.