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

Начиная

В своем проекте я использую Amazon s3 для хранения изображений и графическую магию (http://www.graphicsmagick.org/) для изменения размера изображений. Когда пользователь загружает фотографию, я загружаю полноразмерную фотографию во временное ведро, а затем запускаю бэкэнд для загрузки файла из временного ведра и использую графическую магию, чтобы разделить изображение на малое, среднее и большое. размер.

Причина, по которой я загружаю во временное ведро, а затем загружаю его на бэкэнд, заключается в том, что графическая магия может работать только на бэкэнде, а изображения, как правило, слишком велики для передачи через http без необходимости выполнять многостраничный HTTP POST, и не вдаваясь в подробности проекта, над которым я работал, было проще / эффективнее загружать из внешнего интерфейса. Вы можете увидеть, как я сделал это здесь, но знайте, что это может не сработать, как есть для вашего проекта.

Если вы не так хорошо понимаете обещания или обещание, не волнуйтесь. строка 45 принимает массив размеров ([50, 200, 500]) и назначает каждому размеру в массиве новую функцию процесса с размером в качестве параметра. Таким образом, действия переменных по существу становятся такими: [process (50), process (200), process (500)], а строка 46 берет этот массив и делает его исполняемым обещанием, которое не выполняется then () до тех пор, пока каждое из обещаний в массив выполнены.

Единственная действительно важная часть приведенного выше кода - это строка 21, которая удаляет расширение файла для имени изображения и заменяет его на «_ [размер] .jpg», то есть image.png = ›image_50.jpg, image_200.jpg, image_800. jpg. Это необходимо для того, чтобы загрузчик изображений мог получить правильный размер.

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

post: {
  id: 1,
  body: 'lorem ipsum',
  image: {
    url: {
      sm: s3BucketUrl/image_50.jpg,
      md: s3BucketUrl/image_200.jpg,
      lg: s3BucketUrl/image_800.jpg
    }
  }
}

Директива загрузчика изображений

Если вы не понимаете, как работают директивы Angular, я бы порекомендовал сначала прочитать это.

Давайте разберем директиву.

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

вот пример использования директивы:

<img  
  src="{{profileImage?.url?.sm}}"   
  image-loader  
  [imgSize]="lg"  
  [fallback]="/assets/fallback-image.jpg"     
  (emitOnError)="handleImageError()" 
/>

в процессе()

Вернемся к директиве. Строка 35–41 присоединяет слушателей к функциям загрузки изображения и onerror, чтобы позволить нам запускать код при возникновении любого из этих событий. и дает нам функции для остановки слушателей, когда мы закончим загрузку изображения.

ПРИМЕЧАНИЕ: НИКОГДА НЕ ИСПОЛЬЗУЙТЕ (onload) или (onerror) внутри вашего html-шаблона в ваших тегах img. Это откроет ваше приложение для возможных XSS-атак! : ’(

Давайте посмотрим на нашу пользовательскую функцию onLoad в строке 63. Сначала мы останавливаем приложение от прослушивания событий onload. В строке 65 мы разделяем строку src по каждому «_» и присваиваем ее новому массиву. Затем мы вставляем последний элемент в массиве, который будет «_50.jpg», поскольку это был небольшой размер изображения. И снова объедините массив, вернув все символы «_», которые были удалены функцией разделения. Наконец, мы запускаем loadLargeImage ().

loadLargeImage ()

Сначала в строке 44 мы добавляем суффикс и расширение большого изображения. В данном случае это «_800.jpg». Мы определяем новое изображение и называем его largeImage, даем ему источник, который должен быть URL-адресом большого изображения, которое мы создали, и ждем, пока оно завершит загрузку.

Когда загрузка завершится, мы используем Angular Renderer2 для замены исходного элемента (элемента img, в который была помещена директива) на источник большого изображения. И вуаля! Оно работает!

onError ()

Если изображение не работает по какой-либо причине. Директива заменит собственный элемент src резервным изображением src с функцией onError.

ngOnDestroy ()

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

Заключение

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

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

Спасибо за прочтение! ❤

- Лукас