[英]I have a ton of images. How to make them lazy-load on demand as they scroll into view?
[英]How to lazy load images and make them available for print
有些網站有很多圖片,所以延遲加載似乎適合減少加載時間和數據消耗。 但是,如果您還需要支持該網站的打印呢?
我的意思是,您可以嘗試檢測打印事件,然后加載圖像,如下所示:
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
注意:這是一張一比一像素的 gif 虛擬圖像。
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
。
如果圖像被緩存,這將正常工作,但那又不是重點。 圖像應全部加載,然后出現在打印屏幕中。
你有什么想法? 有沒有人成功實現了可打印的延遲加載插件?
在檢測到打印對話框后,我嘗試將用戶重定向到網站的標記版本,即website.com?print=true
,其中延遲加載已停用,所有圖像都正常加載。
此方法通過在此已標記的可打印頁面版本中應用window.print()
方法得到改進,在所有圖像加載完成后打開一個新的打印對話框,同時顯示“等待它”消息頁面頂部。
重要提示:此方法在 Chrome 中進行了測試,它在 Firefox 和 Edge 中都不起作用(因此這不是答案,而是見證)。
它在 Chrome 中有效,因為當您重定向到另一個網站時打印對話框會關閉(在這種情況下,相同的 url 但已標記)。 在 Edge 和 Firefox 中,打印對話框是一個實際的窗口,它不會關閉它,因此非常不可用。
根據您想要的功能,我不太確定您想要做的事情是否可行。 作為開發人員,我們並不能真正控制用戶的瀏覽器。 以下是我對為什么這不完全可能的想法。
將事件掛鈎並加載丟失的圖像不會讓您保證圖像會從服務器進入您的頁面。 更具體地說,為您的打印預覽生成的 PDF 將在您的圖像完成加載之前生成, img.src = "..."
是異步的。 不幸的是,您也會在onbeforeprint
上遇到類似的問題。 有時有效,有時無效(例如,您的小提琴在 safari 中測試時有效,但在 Chrome 中無效)
你不能停止或停止打印調用——你不能強迫瀏覽器等待你的圖像在延遲加載上下文中完成加載。 (我曾經讀過一些關於使用警報來實現這一點的東西,但它對我來說似乎真的很老套,更多的是對打印的威懾而不是拖延)
您不能強制img.src
在延遲加載上下文中同步獲取該數據。 有一些方法可以做到這一點,但它們是聰明的黑客——被稱為純粹的邪惡,可能並不總是有效。 我找到了另一個類似方法的鏈接
所以我們有一個問題,如果圖像在打印事件觸發時沒有加載,我們不能強制瀏覽器等待它們完成。 當然,我們可以掛鈎並在打印時獲取這些圖像,但如上所述,我們不能等待這些資源在打印預覽彈出之前加載。
您幾乎可以通過同步 XMLHttpRequest 僥幸逃脫。 同步 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 媒體),上面寫着“圖像仍在加載,取消您的打印請求並重試”,當圖像完成加載時,刪除來自 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=""
}
}
})
});
我編寫了一個延遲加載 jquery 插件,它支持使用 window.onbeforeprint 事件和 mediaQueryListeners 在打印時顯示圖像。 https://github.com/msigley/Unveil-EX/
//declare custom onbeforeprint method
const customOnBeforePrint = () => {
const smoothScroll = (h) => {
let i = h || 0;
if (i < 200) {
setTimeout(() => {
window.scrollTo(window.scrollY, window.scrollY + i);
smoothScroll(i + 10);
}, 10);
}
};
let height = document.body.scrollHeight;
let newHeight;
while (true) {
smoothScroll(100);
if (newHeight === height) break;
height = newHeight;
}
};
//override the onbeforeprint method
window.onbeforeprint = customOnBeforePrint;
將該塊復制並粘貼到 devtool 的控制台中,然后嘗試單擊打印按鈕。 該解決方法對我有用。
對於與我在同一條船上的人:當使用瀏覽器本機loading="lazy"
時,您可以在打印時簡單地刪除該屬性。 下面是我的 jQuery 實現。
window.onbeforeprint = function () {
$('img').each(function () {
$(this).removeAttr('loading')
});
}
然后,Chrome 將加載所有圖像,並在打印時顯示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.