Подтвердить что ты не робот

Как ленить загружать изображения и делать их доступными для печати

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

Я имею в виду, вы можете попытаться обнаружить событие печати, а затем загрузить изображения с чем-то вроде этого:

HTML

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

Примечание: это изображение размером в один пиксель gif.

JavaScript

window.addEventListener('DOMContentLoaded', () => {
  img = document.querySelector('img');
  var isPrinting = window.matchMedia('print');
  isPrinting.addListener((media) => {
    if (media.matches) {
      img.src = 'http://unsplash.it/500/300/?image=705';
    }
  })
});

Примечание: если вы попробуете это на игровой площадке кода, удалите событие DOMContentLoaded (или просто выполните следующие действия: JSFiddle | Codepen).

Примечание. Я не стал беспокоиться о onbeforeprint и onafterprint для очевидных причин.

Это будет работать отлично, если изображение будет кэшировано, но опять же, что точно не точка. Изображение/с должны загружаться, а затем отображаться на экране печати. ​​

Есть ли у вас идеи? Кто-нибудь успешно реализовал плагин lilyloading для печати?

Update

Я попробовал перенаправить пользователя после обнаружения диалогового окна печати на отмеченную версию веб-сайта a.k.a website.com?print=true, где lazyloading отключен и все изображения загружаются нормально.

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

Важное примечание: этот метод был протестирован в Chrome, он не работает в Firefox и Edge (следовательно, почему это не ответ, а свидетельство).

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

4b9b3361

Ответ 1

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

  • Привлечение события к загрузке и загрузке ваших недостающих изображений не позволит гарантировать, что изображения сделают это с сервера на вашей странице. Более конкретно, PDF, созданный для вашего предварительного просмотра, будет генерироваться до того, как ваши изображения будут загружены, а img.src = "..." будет асинхронным. К сожалению, вы столкнулись с аналогичными проблемами с onbeforeprint. Иногда это работает, иногда это не так (например, ваша скрипка работала при тестировании в сафари, но не в Chrome)

  • Вы не можете останавливать или останавливать вызов печати - вы не можете заставить браузер ждать, пока ваше изображение закончит загрузку в ленивом контексте загрузки, (Я читал что-то об использовании предупреждений для достижения этого один раз, но мне показалось, что это действительно вредно для меня, было скорее сдерживающим фактором для печати, чем срывом)

  • Вы не можете заставить img.src синхронизировать данные в контексте ленивой нагрузки. Есть некоторые способы сделать это, но они умные хаки - называются чистым злом и могут не работать всегда. Я нашел другую ссылку с аналогичным подходом

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

Потенциальное решение (вдохновленное ссылками в третьей строке, а также эта ссылка)

Вы можете почти уйти с синхронным XMLHttpRequest. Syncrhonous XMLHTTPRequests не позволит вам изменить responseType, они всегда являются строками. Тем не менее, вы можете преобразовать строковое значение в arrayBuffer, закодировав его в кодировке base-64, и установите src в dataURL (см. Ссылку, на которую ссылаются умные хаки), однако, когда я пробовал это, я получил ошибку в jsfiddle - так было бы, если бы все было правильно настроено, теоретически. Я не решаюсь сказать "да", потому что я не смог заставить скрипку работать со следующим (но это маршрут, который вы могли бы изучить!).

var xhr = new XMLHttpRequest();
xhr.open("GET","http://unsplash.it/500/300/?image=705",false);
xhr.send(null);
if (request.status === 200) {
    //we cannot change the resposne type in synchronous XMLHTTPRequests
    //we can convert the string into a dataURL though
    var arr = new Uint8Array(this.response);
    // Convert the int array to a binary string
    // We have to use apply() as we are converting an *array*
    // and String.fromCharCode() takes one or more single values, not
    // an array.
    var raw = String.fromCharCode.apply(null,arr);

    // This is supported in modern browsers
    var b64=btoa(raw);
    var dataURL="data:image/jpeg;base64,"+b64;
    img.src = dataURL;
}

Работайте, чтобы улучшить пользовательский интерфейс

Что-то, что вы могли бы сделать, это текст, который отображается только в печатной версии вашей страницы (через @print css media), в котором говорится, что "изображения по-прежнему загружаются, отменяют запрос на печать и повторите попытку" и когда изображения завершена загрузка, удалите, что "все еще ожидание ресурсов снова пытается отправить сообщение" из DOM. Дальше вы можете обернуть свой основной контент внутри элемента, который не отображает отображение, пока контент не загружается, поэтому все, что вы видите, это сообщение в диалоговом окне предварительного просмотра печати. ​​

Отключение кода, который вы опубликовали, может выглядеть примерно так (см. обновленный jsfiddle):

CSS

.printing-not-ready-message{
  display:none;
}
@media print{
  .printing-not-ready-message{
    display:block;
  }
  .do-not-print-content{
    display:none;
  }
}

HTML

<div class="printing-not-ready-message">
Images are still loading please cancel your preview and try again shortly.
</div>
<div class="do-not-print-content">
    <h1>Welcome to my Lazy Page</h1>
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
    <p>Insert some comment about picture</p>
</div>

JavaScript

window.addEventListener('DOMContentLoaded', () => {
  img = document.querySelector('img');
  var isPrinting = window.matchMedia('print');
  isPrinting.addListener((media) => {
    if (media.matches) {
      img.src = 'http://unsplash.it/500/300/?image=705';
      //depending on how the lazy loading is done, the following might
      //exist in some other call, should happen after all images are loaded.
      //There is only 1 image in this example so this code can be called here.
      img.onload = ()=>{
          document.querySelector(".printing-not-ready-message").remove();
          document.querySelector(".do-not-print-content").className=""
      }
    }
  })
});

Ответ 2

Я являюсь автором сценария vanilla-lazyload, и недавно я разработал функцию, которая делает возможной печать всех изображений!

Протестировано в кросс-браузере с использованием этого кода репо, который доступен здесь.

Посмотрите и дайте мне знать, что вы думаете! Я открыт для получения запросов на GitHub, конечно.

Ответ 3

Я написал плагин для отложенной загрузки jquery, который поддерживает показ изображений на печати с использованием событий window.onbeforeprint и mediaQueryListeners. https://github.com/msigley/Unveil-EX/

Ответ 4

Google объявил о новом атрибуте тега img который автоматически обрабатывает отложенную загрузку изображений в Google I/O 19. Это работает следующим образом:

<img src="IMAGE_URL" alt="IMAGE_DESCRIPTION" loading="lazy">

Новый атрибут (loading = "lazy") поддерживается в chrome и больше не нуждается в плагине или фреймворке.