JavaScript模仿Pinterest實(shí)現(xiàn)圖片預(yù)加載功能
前言
對(duì)于Pinterest網(wǎng)站,從前端設(shè)計(jì)出發(fā)的話,我們一定不會(huì)忘記我們?cè)?jīng)非常流行的瀑布流布局。但是今天,給大家簡(jiǎn)要分析下 Pinterest上另外一項(xiàng)非常值得借鑒圖片加載細(xì)節(jié)。
看看下面的截圖:

大家可以感覺到圖片出來(lái)的時(shí)候預(yù)先繪制輪廓,重點(diǎn)是預(yù)制區(qū)域的顏色采用與圖片較為相似的色彩值,當(dāng)圖片加載完全后,會(huì)有種漸入的效果。
其中谷歌的圖片搜索也用到了類似效果:

我們稱之為這種效果為Color Placeholder [色彩預(yù)置],當(dāng)圖片加載的時(shí)候,我們優(yōu)先顯示其所在容器的背景顏色(如同很多會(huì)顯示一個(gè)加載的gif),由于受限于不同的圖片和大小,因此相比與齊刷刷的加載gif,不同色塊體驗(yàn) 可能 更好吧(至少Pinterest Google這么認(rèn)為吧).
實(shí)現(xiàn)步驟
接下來(lái)我們進(jìn)入正題,如何自己實(shí)現(xiàn)這樣的動(dòng)畫加載效果(實(shí)現(xiàn)的方式肯定有很多的也歡迎大家提出更好的思路)
我們先定義下基本的html結(jié)構(gòu)
<!--一個(gè)post當(dāng)作一個(gè)單位--> <div class="post"> <div class="image-bg" style="background-color:#141646"> <img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/89388038777855.Y3JvcCwxMDk1LDg1NiwyNTIsMjE.png" /> </div> <p class="title">Mars</p> </div>
再看下css設(shè)置
.image-bg{
background: #e1e1e1;
}
img {
width:100%;
opacity: 0;
transition: opacity .2s ease-in .25s;
}
.loaded img {
opacity: 1;
}
圖片默認(rèn)是透明度為0,當(dāng)加載完成后設(shè)置為1就行啦。
$(function() {
$('.post img').each(function() {
var el = this;
var image = new Image();
image.src = el.src;
image.onload = function() {
$(el).parent().addClass('loaded');
}
})
})
大概基本思路就是這些,但是這里面最核心的就是確定所謂的Dominant Color(圖片中主要色彩)。
完整示例如下:
<!doctype html>
<html lang="en">
<head>
<title>實(shí)現(xiàn)類似Pinterest 的圖片預(yù)加載功能</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="stylesheet" />
<style type="text/css">
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
font-size: 62.5%;
-webkit-tap-highlight-color: transparent
}
body {
font-family: 'Helvetica Neue','\5FAE\8F6F\96C5\9ED1','\9ED1\4F53',sans-serif;
letter-spacing: .01rem;
font-size: 15px;
line-height: 1.75em;
color: #3A4145;
-webkit-font-feature-settings: 'kern' 1;
-moz-font-feature-settings: 'kern' 1;
-o-font-feature-settings: 'kern' 1;
}
h1{
padding-top: 40px;
text-align: center;
}
.main{
width: 720px;
margin: 80px auto;
text-align: center;
}
.post{
margin: 10px;
font-size: 18px;
color:#666;
}
.title{
line-height: 30px;
}
.image-bg{
background: #e1e1e1;
}
img {
width:100%;
opacity: 0;
transition: opacity .2s ease-in .25s;
}
.loaded img {
opacity: 1;
}
</style>
<script src="http://s1.vued.vanthink.cn/jquery-1.10.2.min.js"></script>
</head>
<body class="doc">
<h1>實(shí)現(xiàn)類似Pinterest 的圖片預(yù)加載功能</h1>
<div class="main row">
<div class="col-md-6">
<div class="post">
<div class="image-bg" style="background-color:#141646">
<img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/89388038777855.Y3JvcCwxMDk1LDg1NiwyNTIsMjE.png" />
</div>
<p class="title">Mars</p>
</div>
</div>
<div class="col-md-6">
<div class="post">
<div class="image-bg" style="background-color:#3e90dc;" >
<img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/1f430b36513911.Y3JvcCw4MjEsNjQyLDEwMSwzMA.jpg" />
</div>
<p class="title">Grass</p>
</div>
</div>
<div class="col-md-6">
<div class="post">
<div class="image-bg" style="background-color:#09171e;" >
<img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/4bfb7136056367.Y3JvcCw5NTgsNzQ5LDIyMCwyNg.jpg" />
</div>
<p class="title">journet to the west2</p>
</div>
</div>
<div class="col-md-6">
<div class="post">
<div class="image-bg" style="background-color:#d4cab1;" >
<img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/96ed6c36255639.Y3JvcCw1NDksNDI5LDEyNiwxODU.png" />
</div>
<p class="title">Marriage</p>
</div>
</div>
<div class="col-md-6">
<div class="post">
<div class="image-bg" style="background-color:#fff8fa;" >
<img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/ce4a4336970823.Y3JvcCwxMDk1LDg1NiwyNTIsMjE.png" />
</div>
<p class="title">Birthday Card</p>
</div>
</div>
<div class="col-md-6">
<div class="post">
<div class="image-bg" style="background-color:#fff;" >
<img width="310" height="242" src="https://mir-s3-cdn-cf.behance.net/projects/404/fa5dec36514827.Y3JvcCwxMDk1LDg1Niw0ODUsMTY.png" />
</div>
<p class="title">Cup</p>
</div>
</div>
</div>
<script type="text/javascript">
$(function() {
$('.post img').each(function() {
var el = this;
var image = new Image();
image.src = el.src;
image.onload = function() {
$(el).parent().addClass('loaded');
}
})
})
</script>
</body>
</html>
設(shè)置背景的顏色
如果你用photoshop打開一張圖片的話,你只需要幾步就可以確定你希望得到的顏色: 濾鏡 -> 模糊 -> 平均即可。

當(dāng)然這是針對(duì)你所能處理的圖片,如果面對(duì)海量的圖片的話,這個(gè)時(shí)候我們需要用程序去實(shí)現(xiàn)。
尋找到一張圖片較為明顯的顏色,需要在三維空間中找到一些聚合的點(diǎn)。如果自己寫的話,需要去了解一些聚合算法。當(dāng)然自己并不打算去寫更多的內(nèi)容關(guān)于如何去進(jìn)行圖片的這些顏色的生成,這恐怕不是一篇文章能給說(shuō)完的。實(shí)際上你安裝ImageMagick就可以簡(jiǎn)單的實(shí)現(xiàn)預(yù)期效果:
convert path/or/url/to/image.png -resize 1x1 txt:-
但是這個(gè)不太適合我們寫程序的。我們可以使用第三方的npm gm
var gm = require('gm');
gm('demo1.png')
.resize(120, 120)
.colors(1)
.toBuffer('RGB', function (error, buffer) {
console.log(buffer.slice(0, 3));
});
運(yùn)行輸出效果如下:
~ node gm.js ./demo1.png: <Buffer 34 29 3b> ./demo2.png: <Buffer cf c3 ad>
對(duì)比圖如下:

因此借助程序,我們可以在保存圖片的時(shí)候進(jìn)行顏色采集,代碼中通過(guò)先將圖片進(jìn)行大小調(diào)整,實(shí)際是出于性能的考慮。有助于節(jié)約運(yùn)算時(shí)間。除此之外embed.ly也開放了對(duì)應(yīng)的API,方便你獲取網(wǎng)絡(luò)圖片的主要色彩。
如果我們能夠有途徑獲取這樣的顏色的話,自然整體功能就沒有什么難度了。
擴(kuò)展

其實(shí)除了純粹的顏色背景外,我們還可能會(huì)遇到類似 medium 的圖片(參考上圖)預(yù)加載技術(shù),才開始圖片是模糊的。實(shí)際上我們可以通過(guò)插件生成一張幾素的小圖片,然后運(yùn)用上高四模糊濾鏡,然后等待原圖加載完畢后,我們?cè)陲@示原來(lái)的圖片。
var gm = require('gm');
gm('demo1.png')
.resize(4, 4)
.toBuffer('GIF', function (error, buffer) {
console.log('data:image/gif;base64,' + buffer.toString('base64'));
});
<div class="image-bg" style="background-color:#141646"> <img src="data:image/gif;base64,R0lGODlhBAADAPMJACwlPjAmPDUqOzgrOgQPSgkSShAVRhEWRplcFsR3EAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAEAAMAAAQJ0" width="310" height="242" real-src="https://mir-s3-cdn-cf.behance.net/projects/404/89388038777855.Y3JvcCwxMDk1LDg1NiwyNTIsMjE.png" />
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
- JS實(shí)現(xiàn)圖片預(yù)加載無(wú)需等待
- js 實(shí)現(xiàn)圖片預(yù)加載(js操作 Image對(duì)象屬性complete ,事件onload 異步加載圖片)
- javascript預(yù)加載圖片、css、js的方法示例介紹
- 純JS圖片批量預(yù)加載技術(shù)代碼
- js 利用image對(duì)象實(shí)現(xiàn)圖片的預(yù)加載提高訪問(wèn)速度
- javascript 也來(lái)玩玩圖片預(yù)加載
- 利用CSS、JavaScript及Ajax實(shí)現(xiàn)高效的圖片預(yù)加載
- 再談javascript圖片預(yù)加載技術(shù)(詳細(xì)演示)
- JS圖片預(yù)加載 JS實(shí)現(xiàn)圖片預(yù)加載應(yīng)用
- js圖片預(yù)加載示例
相關(guān)文章
JavaScript Date對(duì)象使用總結(jié)
js 日期對(duì)象的一些方法總結(jié)2009-05-05
詳解JS如何實(shí)現(xiàn)文字溢出時(shí)用省略號(hào)...顯示
這篇文章主要為大家詳細(xì)介紹了JavaScript如何實(shí)現(xiàn)當(dāng)文本內(nèi)容過(guò)長(zhǎng)時(shí),中間顯示省略號(hào)...,兩端正常展示,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
js實(shí)現(xiàn)圖片無(wú)縫滾動(dòng)特效
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)圖片無(wú)縫循環(huán)滾動(dòng)特效的相關(guān)資料,本實(shí)例在網(wǎng)頁(yè)中較為常見,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01
js控制文本框只輸入數(shù)字和小數(shù)點(diǎn)的方法
這篇文章主要介紹了js控制文本框只輸入數(shù)字和小數(shù)點(diǎn)的方法,實(shí)例分析了javascript使用正則表達(dá)式實(shí)現(xiàn)限制數(shù)字和小數(shù)點(diǎn)的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
javascript基于牛頓迭代法實(shí)現(xiàn)求浮點(diǎn)數(shù)的平方根【遞歸原理】
這篇文章主要介紹了javascript基于牛頓迭代法實(shí)現(xiàn)求浮點(diǎn)數(shù)的平方根,簡(jiǎn)單說(shuō)明了牛頓迭代法的原理,并結(jié)合實(shí)例分析了javascript基于遞歸的數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
轉(zhuǎn)換json格式的日期為Javascript對(duì)象的函數(shù)
項(xiàng)目中碰到了用jQuery從后臺(tái)獲取的json格式的日期的字符串,需要將此字符串轉(zhuǎn)換成JavaScript的日期對(duì)象,記在此處,以備后用。2010-07-07

