頁中預加載圖片是提高用戶體驗的一個很好方法。圖片預先加載到瀏覽器中,訪問者便可順利地在你的網站上沖浪,并享受到極快的加載速度。這對圖片畫廊及圖片占據很大比例的網站來說十分有利,它保證了圖片快速加載,特別是一些大型的電商網站就常用!幫助用戶在瀏覽你網站內容時獲得更好的用戶體驗,下面就來說說實現圖片預加載的方法。
一、使用JavaScript實現預加載
提供兩種這樣的預加載方法,它們可以很漂亮地工作于所有現代瀏覽器之上。
只需簡單編輯、加載所需要圖片的路徑與名稱即可,很容易實現:
該方法尤其適用預加載大量的圖片。畫廊網站使用該技術,預加載圖片數量達50多張的時候。將該腳本應用到登錄頁面,只要用戶輸入登錄帳號,大部分畫廊圖片將被預加載。
另外一種方法與上面的方法類似,也可以預加載任意數量的圖片。將下面的腳本添加入任何Web頁中,根據程序指令進行編輯即可。
每加載一個圖片都需要創建一個變量,如“img1 = new Image();”,及圖片源地址聲明,如“img3.src = "../path/to/image-003.gif";”。參考該模式,你可根據需要加載任意多的圖片。
二、用CSS實現預加載
單純使用CSS,可容易、高效地預加載圖片,代碼如下:
#preload-01 { background: url(-01.png) no-repeat -9999px -9999px; }#preload-02 { background: url(-02.png) no-repeat -9999px -9999px; }#preload-03 { background: url(-03.png) no-repeat -9999px -9999px; }
將這三個ID選擇器應用到HTML元素中,我們便可通過CSS的background屬性將圖片預加載到屏幕外的背景上。只要這些圖片的路徑保持不變,當它們在Web頁面的其他地方被調用時,瀏覽器就會在渲染過程中使用預加載(緩存)的圖片。簡單、高效,不需要任何JavaScript。
者:麥樂
來源:恒生LIGHT云社區
想要得到更好的性能體驗,只靠資源壓縮與恰當的文件格式選型,是很難滿足期望的。我們還需要針對資源加載過程進行優化。
下圖是京東商城的手機端首頁,當元素沒有滑動到視線內時,圖片src屬性放置了一個很小的圖片,init_src屬性放置了真正的圖片,只要當該元素滑動到視線內部,才會將init_src屬性賦值給src去加載真實的圖片,這就是一個簡單的圖片延遲加載的過程。
就是事件監聽的方式,通過監聽scroll事件與resize事件,并在事件的回調函數中去判斷,需要進行延遲加載的圖片是否進入視窗區域。
我們只需要關注三個屬性。
加入頁面中有多張這樣的圖片需要加載。具體的JavaScript實現邏輯如下,在文檔的DOMContentLoaded事件中,添加延遲加載處理邏輯,首先獲取class屬性名為lazy的所有〈img〉標簽,將這些標簽暫存在一個名為lazyImages的數組中,表示需要進行延遲加載但還未加載的圖片集合。當一個圖片被加載后,便將其從lazyImages數組中移除,直到lazyImages數組為空時,表示所有待延遲加載的圖片均已經加載完成,此時便可將頁面滾動事件移除。
這里使用了getBoundingClientRect()函數獲取元素的相對位置.
rectObject = object.getBoundingClientRect();
rectObject.top:元素上邊到視窗上邊的距離;
rectObject.right:元素右邊到視窗左邊的距離;
rectObject.bottom:元素下邊到視窗上邊的距離;
rectObject.left:元素左邊到視窗左邊的距離;
對于只可上下滾動的頁面,判斷一個圖片元素是否出現在屏幕視窗中的方法其實顯而易見,即當元素上邊緣距屏幕視窗頂部的top值小于整個視窗的高度window.innerHeight時,預加載的事件處理代碼如下:
document.addEventListener(DOMContentLoaded, function() {
const imags = [].slice.call(document.querySelector('.lazy'))
const active = false; // 限制函數被頻繁調動
function load() {
if(active === false) {
active = true
setTimeout(() => {
imags.forEach((img) => {
const objPos = img.getBoundingClientRect();
if(objPos.top <= window.innerHeight && objPos.bottom >=0 && img.display !== 'done') {
img.src = img.dataset.src;
img.classList.remove('lazy')
imags.filter((i) => (i !== img))
if(imags.length === 0) {
document.removeEventListener('scroll', load)
window.removeEventListener('resize', load)
window.removeEventListener('orientationchange', load)
}
}
})
active = false
}, 200)
}
}
document.addEventListener('scroll', load)
window.addEventListener('resize', load)
window.addEventListener('orientationchange', load)
})
這種方式的有點就是兼容性比較好,缺點是頻繁地進行計算必然會影響性能,代碼也會比較繁瑣。
現代瀏覽器已大多支持了Intersection Observer API,用一句話簡述:每當因頁面滾動或窗口尺寸發生變化,使得目標元素(target)與設備視窗或其他指定元素產生交集時,便會觸發通過Intersection Observer API配置的回調函數,在該回調函數中進行延遲加載的邏輯處理,會比傳統方式顯得更加簡潔而高效。
簡單來說,目標元素的可見性變化時,就會調用觀察器的回調函數 callback。
callback一般會觸發兩次。一次是目標元素剛剛進入視口(開始可見),另一次是完全離開視口(開始不可見)。
document.addEventListener(DOMContentLoaded, function() {
const imags = [].slice.call(document.querySelector('.lazy'))
if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
var lazyImgObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry)=> {
if(entry.isIntersecting) {
var lazyImg = entry.target;
lazyImg.src = lazyImg.dataset.src;
lazyImg.classList.remove('lazy');
lazyImgObserver.unobserve(lazyImg)
}
})
})
imags.forEach((img) => {
lazyImgObserver.observe(img)
})
}
})
這種方式判斷元素是否出現在視窗中更為簡單直觀,應在實際開發中盡量使用,但其問題是并非所有瀏覽器都能兼容。
(1)做好盡量完備瀏覽器兼容性檢查,對于兼容Intersection Observer API的瀏覽器,采用這種方式進行處理,而對于不兼容的瀏覽器,則切換回傳統的實現方式進行處理。 (2)使用相應兼容的polyfill插件,在W3C官方GitHub賬號下就有提供。
這種實現方式通過CSS的background-image屬性來加載圖片,與判斷〈img〉標簽src屬性是否有要請求圖片的URL不同,CSS中圖片加載的行為建立在瀏覽器對文檔分析基礎之上。
document.addEventListener(DOMContentLoaded, function() {
const imags = [].slice.call(document.querySelector('.lazy'))
if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
var lazyImgObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry)=> {
if(entry.isIntersecting) {
var lazyImg = entry.target;
lazyImg.classList.add('visible');
lazyImgObserver.unobserve(lazyImg)
}
})
})
imags.forEach((img) => {
lazyImgObserver.observe(img)
})
}
})
這種方式限制于需要提前寫好css樣式。
除了上述通過開發者手動實現延遲加載邏輯的方式,從Chrome 75版本開始,已經可以通過〈img〉和〈iframe〉標簽的loading屬性原生支持延遲加載了,loading屬性包含以下三種取值。
● lazy:進行延遲加載。 ● eager:立即加載。 ● auto:瀏覽器自行決定是否進行延遲加載。
測試:image標簽就是 img
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="js/file2.js"></script> -->
<!-- <script src="js/file3.js"></script> -->
<!-- <link rel="stylesheet" href="css/index.css"> -->
<style>
img {
width: 700px;
height: 200px;
display: block;
}
</style>
</head>
<body>
<imgage loading="lazy" src='./image/home-1.png' alt="photo" />
<imgage loading="lazy" src='./image/home-2.png' alt="photo" />
<imgage loading="lazy" src='./image/home-3.png' alt="photo" />
<imgage loading="lazy" src='./image/home-4.png' alt="photo" />
<imgage loading="lazy" src='./image/home-5.png' alt="photo" />
<imgage loading="lazy" src='./image/home-6.png' alt="photo" />
<imgage loading="lazy" src='./image/home-7.png' alt="photo" />
<imgage loading="lazy" src='./image/home-8.png' alt="photo" />
<imgage loading="lazy" src='./image/home-9.png' alt="photo" />
<imgage loading="lazy" src='./image/home-10.png' alt="photo" />
<imgage loading="lazy" src='./image/home-11.png' alt="photo" />
<imgage loading="lazy" src='./image/home-12.png' alt="photo" />
<imgage loading="lazy" src='./image/home-13.png' alt="photo" />
<imgage loading="lazy" src='./image/home-14.png' alt="photo" />
<imgage loading="lazy" src='./image/home-15.png' alt="photo" />
<imgage loading="lazy" src='./image/home-16.png' alt="photo" />
<imgage loading="lazy" src='./image/home-17.png' alt="photo" />
<imgage loading="lazy" src='./image/home-18.png' alt="photo" />
<imgage loading="lazy" src='./image/home-19.png' alt="photo" />
<imgage loading="lazy" src='./image/home-20.png' alt="photo" />
<imgage loading="lazy" src='./image/home-21.png' alt="photo" />
<imgage loading="lazy" src='./image/home-22.png' alt="photo" />
<imgage loading="lazy" src='./image/home-23.png' alt="photo" />
<imgage loading="lazy" src='./image/home-24.png' alt="photo" />
<imgage loading="lazy" src='./image/home-25.png' alt="photo" />
<imgage loading="lazy" src='./image/home-26.png' alt="photo" />
<imgage loading="lazy" src='./image/home-27.png' alt="photo" />
<imgage loading="lazy" src='./image/home-28.png' alt="photo" />
<imgage loading="lazy" src='./image/home-29.png' alt="photo" />
<imgage loading="lazy" src='./image/home-30.png' alt="photo" />
</body>
</html>
可以看到,首次加載的個數是13個,首屏一般只能放下4個左右,13個以后的img滾動到視線內部會自動去加載。
實踐發現有以下幾個特點:
與JavaScript有關的幾個行為特征:
兩天被django折磨的快崩潰了。要做一個網頁,結果CSS 和圖片總是加載不出來。官方文檔中教了一部分,上網看樂各種教程都不行,研究了好幾個小時,東拼西湊各個地方學一點,終于弄出來了,趕緊記錄下來。
django用的靜態文件路徑:STATICFILES_DIRS部署的方式,文件路徑一定要設置好。
注: python2.7 django1.10.6; 項目mysite,項目下有一個應用myapp
一、目錄結構:
整個目錄結構是這樣的:
| mysite
| —— manage.py
| —— mysite
| —— | —— settings
| —— | ——…(urls等)
| —— templates
| —— myapp
| —— …(views等)
| —— | —— templates
| —— | —— | —— myapp
| —— | —— | —— | —— home.html
| —— | —— | —— | —— static
| —— | —— | —— | —— | —— css
| —— | —— | —— | —— | —— images
注意,文件夾結構比較復雜。
在項目文件夾下有一個templates文件夾,不過這個文件夾暫時沒什么用,可以不用管(我也不知道為什么要有這么個文件夾)。
應用文件夾結構是這樣的:
“myapp/templates/myapp/home.html”;
“myapp/templates/myapp/static/images”;
“myapp/templates/myapp/static/CSS”;
二、設置templates和靜態路徑
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'myapp/templates').replace('\', '/'),
os.path.join(BASE_DIR, 'templates').replace('\', '/')],
}
]
STATIC_ROOT = os.path.join(BASE_DIR, 'myapp/templates/myapp/static').replace('\', '/')
STATICFILES_DIRS = (
('css', os.path.join(STATIC_ROOT, 'css').replace('\', '/')),
('images', os.path.join(STATIC_ROOT, 'images').replace('\', '/')),
)
三、修改urls.py文件
在urls.py開頭加上一句:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
在urls.py的最后加上以下內容:
#設置靜態文件路徑
urlpatterns += staticfiles_urlpatterns()
四、修改html文件
home.html文件相關內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="/static/css/style.css" rel="stylesheet" type="text/css" />
<title>Home</title>
</head>
<body>
<a href="https://www.baidu.com/>
<img src="/static/images/logo.png" alt="logo"/>
</a>
</body>
</html>
改成自己的圖片名稱,注意圖片和link的前綴:/static/images/ 別寫成 static/images/ ,這樣會無法顯示。
感覺自己底子真的太差,這幾天一點一點看官方文檔感到非常吃力,很多地方都不懂,想直接看自己需要的部分又不知道該看哪。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。