Ответ 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=""
}
}
})
});