Управляем загрузкой изображений. Управление загрузкой изображений

На iOS - iPhone, iPod touch 12.05.2019
На iOS - iPhone, iPod touch

Когда делаешь на сайте какую-то галерею, требуется загружать изображения заранее, чтобы в скриптах не возникало ошибок или пользователь не видел куски недогруженных изображений.

В своё время для таких целей я и искал хороший прелоадер, но так и не смог найти решения, которое бы меня полностью удовлетворяло. Пришлось написать свой.

В нём есть базовый функционал, позволяющий выполнять две основные функции: загружать изображения и вызывать после этого коллбэк. Но так же есть и свои фичи. Он может загружать картинки по очереди в том порядке, в котором они были помещены в массив. Не только по одному, а по два-три-N. А на каждую итерацию загрузки может выполнять коллбэк. Но и это ещё не всё: после загрузки последнего изображения выполнится финальный коллбэк, говорящий о том, что все изображения загружены.

Использование

Существует два варианта использования jQuery.preload.
Первый — передавать адрес(а) изображений:

$.preload(images, , );

  • images
    Адрес изображения на вход можно подавать как строкой (для одной картинки), так и массивом.
  • part
    Далее идет необязательный параметр, указывающий по сколько изображений загружать за раз. 0 — значит все разом, значение по умолчанию.
  • callback
    Ну и наконец коллбэк — функция, которая выполнится по завершении загрузки изображения. Ей можно указать свой параметр last , принимающий значение true , если эта часть последняя.

Второй вариант использования — загружать все изображения и фоновые картинки в элементе:

$("#elem").preload();

  • callback
    Функция, которая выполнится после загрузки всех изображений.
Примеры
  • — изображения будут загружаться по одному, после загрузки каждого сработает коллбэк, а после загрузки последнего сработает финальный коллбэк.
  • — коллбэк отображает ранее скрытые, но уже загруженные изображения.

Для корректной работы плагина требуется jQuery версии 1.6 или выше.

  • Перевод
  • Tutorial

Быстрая и плавная загрузка изображений - это одна из немаловажных составляющих хорошего веб-интерфейса. Кроме того, появляется все больше сайтов, использующие крупные фотографии в дизайне, таким проектам особенно важно следить за корректной загрузкой графики. В этой статье описано несколько техник, которые помогут контролировать загрузку изображений.

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


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

Например, чтобы задать соотношение сторон 4:3, можно использовать следующий CSS:

Img_wrapper{ position: relative; padding-top: 75%; overflow: hidden; } .img_wrapper img{ position: absolute; top: 0; width: 100%; opacity: 0; }
Для того, чтобы изображение отображалось в браузере только после полной подгрузки, необходимо добавить событие onload для изображения и использовать JavaScript, который будет обрабатывать событие:


function imgLoaded(img){ var $img = $(img); $img.parent().addClass("loaded"); };
Код функции внутри тега HEAD должен быть расположен в самом конце, после любого jQuery или другого плагина. После полной подгрузки изображения его необходимо показать на странице:

Img_wrapper.loaded img{ opacity: 1; }
Для эффекта плавного появления картинки можно использовать CSS3 transition:

Img_wrapper img{ position: absolute; top: 0; width: 100%; opacity: 0; -webkit-transition: opacity 150ms; -moz-transition: opacity 150ms; -ms-transition: opacity 150ms; transition: opacity 150ms; }
Живой пример этого способа можно .

Использование контейнера для множества изображений Предыдущий способ хорошо подходит для отдельных изображений, а что если на странице их много, например галерея фотографий или слайдер? Подгружать сразу все нецелесообразно - картинки могут много весить. Для решения этой проблемы можно заставить JavaScript"ом загружать только нужные в данный момент времени изображения. Пример HTML-разметки для слайдшоу:


Используем функцию slideLoaded(), чтобы контролировать процесс:

Function slideLoaded(img){ var $img = $(img), $slideWrapper = $img.parent(), total = $slideWrapper.find("img").length, percentLoaded = null; $img.addClass("loaded"); var loaded = $slideWrapper.find(".loaded").length; if(loaded == total){ percentLoaded = 100; // INSTANTIATE PLUGIN $slideWrapper.easyFader(); } else { // TRACK PROGRESS percentLoaded = loaded/total * 100; }; };
Подгруженным изображениям присваивается класс loaded, а также отображается общий прогресс. И снова, JavaScript должен быть помещен в конец тега HEAD, после всего остального.

Кэширование На графически тяжелых сайтах можно в фоновом режиме, незаметно для пользователя, загружать изображения в кэш браузера. Например, есть многостраничный сайт, на одной из внутренних страниц которого есть много графического контента. В этом случае будет целесообразно подгружать изображения в кэш еще до того, как пользователь перешел на нужную страницу. адреса картинок в массиве:

var heroArray = [ "/uploads/hero_about.jpg", "/uploads/hero_history.jpg", "/uploads/hero_contact.jpg", "/uploads/hero_services.jpg" ]
Когда посетитель заходит на сайт, после загрузки главной страницы, начинают загружаться изображения в кэш. Для того, чтобы кэширование не мешало отображению текущего контента, необходимо функционал JavaScript добавить в событие window load:

Function preCacheHeros(){ $.each(heroArray, function(){ var img = new Image(); img.src = this; }); }; $(window).load(function(){ preCacheHeros(); });
Такой способ улучшает удобство использования сайта, однако дает дополнительную нагрузку на сервер. Это нужно иметь в виду при внедрении подобного функционала. Кроме того, необходимо обязательно учитывать возможные пути посетителей на сайте и кэшировать изображения, расположенные на страницах, которые пользователь вероятнее всего посетит. Чтобы понять такие пути по сайту, необходимо анализировать статистику посещаемости.

Загрузка по событию способ заключается в том, что изображения начинают подгружаться после определенного события. Это увеличивает производительность и экономит трафик пользователя. HTML-разметка:


Стоит заметить, что URL изображение задано в data-src, а не в src. Это необходимо, чтобы браузер не загружал картинку сразу. Вместо этого в src загружается прозрачный пиксель в GIF, заданный в base64, что уменьшает количество обращений к серверу.

Остается только при нужном событии изменить значение src на data-src. JavaScript позволяет загружать изображения постепенно:

Function lazyLoad(){ var $images = $(".lazy_load"); $images.each(function(){ var $img = $(this), src = $img.attr("data-src"); $img .on("load",imgLoaded($img)) .attr("src",src); }); }; $(window).load(function(){ lazyLoad(); };

Заключение Нет одного оптимального способа для того, чтобы управлять загрузкой изображений на сайте. В каждом конкретном случае необходимо выбирать подходящий метод, а также комбинировать несколько, если это целесообразно. Одними из главных моментов, на которые необходимо обратить внимание - это производительность и трафик. Проще говоря, в первую очередь стоит подумать о том, как будет удобнее пользователю сайта.

Зачем вообще нужна изображений? Представим себе, что у Вас есть элемент на странице сайта, и Вы хотите, чтобы при наведении на него мышкой показывалась или изменялась его фоновая картинка. Проблем, в принципе, не должно возникнуть, все решается просто: при создании сайта в стилевой разметке для псевдокласса:hover нужного элемента свойству background указываем путь к необходимому изображению.

Но есть один нюанс, если событие hover возникает первый раз, то для загрузки изображения может потребоваться время. Пусть этот временной интервал будет и небольшим, но все же, иногда можно заметить короткую раздражающую задержку между наведением курсора над элементом и полным отображением изображения. Понятно, что в последующем, таких задержек не будет, так как браузеры добросовестно закешируют изображение. Но, как известно, первое впечатление от Вашего сайта должно быть только положительным, и не нужно его портить такими мелочами, тем более что их можно избежать. Как же решить такую, хоть и небольшую, но своеобразную проблему. Методов есть много, здесь наша веб студия познакомит Вас только с теми, которые решаются средствами css .

Первый прием заключается в том, что сразу же загружаем графическую составляющую, а потом убираем ее с видимой области при помощи свойства background-position, например установлением следующих смещений по x и y - -9999px -9999px. При наступлении события hover, применяем уже реальные значения, например, bottom left.

А что делать, если элемент уже имеет фоновое изображение , и при наведении курсора мыши его необходимо сменить. Приведенная выше техника уже не подойдет в качестве решения. Обычно в таких случаях используют спрайты (комбинированные фоновые картинки), когда сдвигается позиция фона. Если же Вам такой способ недоступен, попробуйте следующее. Примените изображение для другого существующего элемента на странице, но который не имеет фоновой картинки.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }

#grass:hover { background: url(images/grass.png) no-repeat; }

Идея заключается в создании новых элементов, которые нужны только для предварительной загрузки изображений. Вы скажете, что это не самый лучший способ, ведь количество таких пустышек может быть огромным, решение же, далеко не будет элегантным. И Вы будете совершенно правы. Нам не нужны дополнительные элементы, так как мы можем со спокойной душой использовать и существующие. Все что нам необходимо, это использовать псевдоклассы:after или:before.

#something:before {

content: url("./img.jpg");

visibility:hidden;

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

Конечно же, можно применять для этих целей и javascript, но если Вам для создания сайта , достаточно будет приведенных выше решений, то почему бы ими и не воспользоваться.

Изображения, хорошие и качественные, являются главным преимуществом сайта. Но основной бедой в использовании изображений является их размер: обычно это не менее 50% от размера сайта и не менее 300 Кб на каждой странице составляются изображения (такой объем информации на мобильном телефоне загружается примерно 1,5 секунды, на стационарном компьютере - 0,2-0,3 секунды).

Что же с ними делать?

Последовательные изображения и PNG

Проблема с размером изображений является уже очень старой и хорошо изученной. Лучшее, что вы можете сделать прямо сейчас, - это использовать progressive (последовательные) JPEG формат для полноцветных изображений (фотографии) и PNG формат для всех других файлов (например, фоновых изображений или иконок).

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

PNG формат за счет максимального сжатия палитры и представления индексированных изображений (с небольшим количеством цветов) может передать даже большое по площади изображение при помощи небольшого объема информации. Это крайне критично для эффективности вашего сайта: если вы не можете ухудшить качество представления информации, то в состоянии свести размер этой информации к минимуму.

«Ленивая» загрузка (lazy load)

Следующим шагом в оптимизации размера загружаемой информации стала загрузка изображений, необходимых только для отображения первого экрана сайта. Например, если у вас каталог с десятками позиций, а на первом экране помещается всего 8 - разумно загрузить сначала только 8 изображений. Это (визуально) сильно ускорит полную загрузку страницы сайта. А когда пользователь покручивает страницу дальше - то загружать все изображения для дальнейших частей страницы. При этом показывать индикатор загрузки на месте загружаемых изображений.

Существует огромное количество решений, так или иначе реализующий этот метод - lazyload - вы легко найдете подходящий вам плагин и сможете его установить. Это такого подхода, однако, есть пара минусов: пользователю приходится ждать при прокрутке страницы, пока загрузятся «отложенные» изображения и реализация плагина может быть не совсем корректной, что приведет к замедлению работы сайта на всех устройствах. Дополнительно, нужно гарантировать доступность изображений в коде страницы для поисковых роботов.

Непростая задача, правда?

Улучшаем lazyload

Существует несколько реализаций lazyload - в частности, unveil - которые обошли первый недостаток: загрузка изображений может быть отложена ровно до того момента, когда мы покажем пользователю «готовый» сайт (обычно это момент готовности структуры страницы - DOMready - но иногда и полная загрузка страницы - onload). И начнем загружать все изображения сразу после этого события. Если пользователь потратит 2-3 секунды на первичное ознакомление с содержимым страницы, то для него загрузка изображений пройдет практически незаметно (браузер уже покажет, что страница готова). Если пользователь все же успеет начать просматривать страницу до того, как у него загрузятся все изображения, то на месте изображений вместо значка от браузера по умолчанию или пустого места будет индикатор загрузки.

Вполне элегантное решение, но его можно улучшить еще, если более тщательно подойти к последовательности загрузки страниц сайта. Рассмотреть, какие виджеты и когда загружаются: чтобы они не вклинились в процесс загрузки изображений. Расположить изображения на 1-2 поддоменах, если их больше 30 - так будет положительных эффект от параллельной загрузки изображений. Возможно, часть изображений перенести на событие полной загрузки, а часть - на событие готовности структуры страницы. В общем, исследовать процесс загрузки сайта более детально и оптимизировать пользовательское восприятие - чтобы сайт выглядел реактивным.

Пред-загрузка изображений (prefetch)

Техническое сообщество на этом не остановилось и пошло в оптимизации процесса загрузки изображений дальше. Что если мы можем предугадать следующее пользовательское действие на сайте - и сразу загрузить требуемые ресурсы (а смые значительные из них - это изображения)? Как это можно сделать?

Техника предварительной загрузки изображений (preload или prefetch) активно используется в различных галереях изображениях - например, Яндекс.Фотки - пока вы просматриваете одно изображения, браузер уже загружает два-три предыдущих и два-три следующих. И покажет их практически моментально после перехода назад или вперед. И это будет реактивно!

Для интернет-магазина можно использовать ту же технику при просмотре отдельных товаров - подгружая сразу изображения из галереи или похожих товаров из рекомендательного сервиса. Это сократит объем передаваемой информации от сайта к пользователю после перехода по новой ссылке и визуально ускорит сайт.

Заключение и список действий

Итак, масса полезной информации. Что же конкретно делать? Вам нужно пройти по следующему списку и проверить, все ли у вас на сайте хорошо. Если нет - то принять соответствующие меры:

  • Полноцветные изображения создаются в последовательных JPEG? Если нет и можно сохранять изображения с потерями качества, то нужно настроить этот формат.
  • Все остальные изображения в PNG? Если нет, то нужно настроить именно этот формат. Дополнительно рекомендуется оптимизировать PNG изображения пакетно или при помощи сервисов .
  • Все ли изображения отображаются в естественных размерах? Часто физические размеры (высота и ширина) у изображения больше размера видимого изображения. Это приводит к рудиментам по качеству и заставляет загружать значительно больше данных, чем нужно. Измените размеры изображений к используемым на сайте (если нужно, создайте дубликаты в других размерах).
  • Изображений на странице больше 20 и они не помещаются на первых двух экранах? Нужно использовать какое-либо решение lazyload для сокращения объема первоначально загружаемой информации.
  • На сайте кроме изображений используется несколько виджетов и кодов статистики? Проверьте диаграмму загрузки сайта и убедитесь, что ценные изображения при отложенной загрузке передаются пользователю в первую очередь.
  • Нужно максимально ускорить сайта, и все пункты уже сделаны? Настройте предварительную загрузку изображений при переходах по страницам сайта. Изучите сценарии использования сайта - и подстройте логику загрузки изображений под них.
  • Это, в принципе, все. Стоит напомнить, что Айри автоматически приводит изображения к минимальному размеру и наилучшему формату без потери качества, а также может динамически выставить правильные размеры для изображений и отложить их загрузку.

    Привносит новое, удивительное API. Если вы соедините это API с элементом то вы можете получить супер современный загрузчик изображений. Эта статья расскажет, как это сделать. Все эти советы хорошо работают в Firefox 4. Также будут описываться некоторые альтернативные способы, чтобы убедиться, что они работают на Webkit-браузерах. Большинство из этих API, не работают в IE, но это довольно простой способ в использовании, и вполне годиться в качестве запасного варианта.

    Было бы неплохо, если бы кто-то отписал в комментариях, как он использует ту или иную технологию уже сейчас в своих проектах.

    Получить изображение

    Чтобы загрузить файл на сервер, Вам понадобится элемент . Но вы также должны позволить пользователю перетаскивать изображения с рабочего стола прямо на веб-страницу Вашего сайта.

    Множественный выбор файлов для загрузки

    Чтобы позволить пользователю выбрать за один раз несколько файлов надо вставить в элемент file атрибут multiple

    Предварительная обработка файлов

    Используем File API

    (Детали работы с File API смотрите )

    После того как вы выбрали файлы в элемент file, датапикером или при помощи drag&drop у Вас есть список файлов готовых к использованию.

    //из type="file" var filesToUpload = input.files; //либо при помощи Drag-and-Drop function onDrop(e) { filesToUpload = e.dataTransfer.files; }

    Убедитесь, что эти файлыявляются изображениями:

    If (!file.type.match(/image.*/)) { // этот файл не изображение };

    Показать миниатюрку/превьюшку

    Есть два варианта. Вы можете использовать FileReader (из File API), или использовать новый метод createObjectURL () .

    createObjectURL()

    Var img = document.createElement("img"); img.src = window.URL.createObjectURL(file);

    FileReader

    Var img = document.createElement("img"); var reader = new FileReader(); reader.onload = function(e) {img.src = e.target.result} reader.readAsDataURL(file);

    Используем Canvas

    Вы можете нарисовать файл на элементе для последующей его обработки

    Var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0);

    Изменение размера изображения

    Люди привыкли загружать изображения прямо из своей камеры. Это дает высокое разрешение и чрезвычайно тяжелые (несколько мегабайт) файлы. В зависимости от использования, вы можете изменить размер таких изображений. Фокус в том, чтобы просто иметь небольшой canvas(800 × 600, например) и нарисовать это изображение в этот canvas. Конечно, вам придется изменить размеры canvas"а, чтобы сохранить отношения сторон изображения.

    Var MAX_WIDTH = 800; var MAX_HEIGHT = 600; var width = img.width; var height = img.height; if (width > height) { if (width > MAX_WIDTH) { height *= MAX_WIDTH / width; width = MAX_WIDTH; } } else { if (height > MAX_HEIGHT) { width *= MAX_HEIGHT / height; height = MAX_HEIGHT; } } canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, width, height);

    Редактирование изображения

    Теперь у вас есть изображение в canvas. Теперь Ваши возможности безграничны. Допустим, вы хотите применить фильтр сепия:

    Var imgData = ctx.createImageData(width, height); var data = imgData.data; var pixels = ctx.getImageData(0, 0, width, height); for (var i = 0, ii = pixels.data.length; i < ii; i += 4) { var r = pixels.data; var g =pixels.data; var b = this.pixels.data; data = (r * .393) + (g *.769) + (b * .189); data = (r * .349) + (g *.686) + (b * .168) data = (r * .272) + (g *.534) + (b * .131) data = 255; } ctx.putImageData(imgData, 0, 0);

    Загрузить с XMLHttpRequest

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

    Как отправить canvas

    Опять же, у Вас есть два варианта. Вы можете конвертировать canvas очень длинный URL или (в Firefox) создать файл из canvas.

    canvas.toDataURL()

    Var dataurl = canvas.toDataURL("image/png");

    Создайте файл из canvas

    Var file = canvas.mozGetAsFile("foo.png");

    Неделимая загрузка

    Разрешить пользователю загрузить только один файл или все файлы, в то же время.

    Показать ход загрузки

    Используйте событие загрузки для создания индикатора:

    Xhr.upload.addEventListener("progress", function(e) { if (e.lengthComputable) { var percentage = Math.round((e.loaded * 100) / e.total); // do something }, false);

    Используйте FormData

    Вы, наверное, вряд ли хотите просто загрузить файл (который может быть легко сделано с помощью: xhr.send (файл)), но также добавить стороннюю информацию (например, ключ и название).

    В этом случае вы должны создать multipart/form-data запрос с помощью объекта FormData

    Var fd = new FormData(); fd.append("name", "paul"); fd.append("image", canvas.mozGetAsFile("foo.png")); fd.append("key", "××××××××××××"); var xhr = new XMLHttpRequest(); xhr.open("POST", "http://your.api.com/upload.json"); xhr.send(fd);


    Откройте Ваше API сайта

    Может быть, вы хотите, чтобы другие сайты, использовали Ваш сайт как сервис.\



    Рекомендуем почитать

    Наверх