前言
對於Pinterest網站,從前端設計出發的話,我們一定不會忘記我們曾經非常流行的瀑布流布局。但是今天,給大家簡要分析下 Pinterest上另外一項非常值得借鑒圖片載入細節。
看看下面的截圖:
大家可以感覺到圖片出來的時候預先繪製輪廓,重點是預製地區的顏色採用與圖片較為相似的色彩值,當圖片載入完全後,會有種漸入的效果。
其中Google的圖片搜尋也用到了類似效果:
我們稱之為這種效果為Color Placeholder
[色彩預置],當圖片載入的時候,我們優先顯示其所在容器的背景顏色(如同很多會顯示一個載入的gif),由於受限於不同的圖片和大小,因此相比與齊刷刷的載入gif,不同色塊體驗 可能 更好吧(至少Pinterest Google這麼認為吧).
實現步驟
接下來我們進入正題,如何自己實現這樣的動畫載入效果(實現的方式肯定有很多的也歡迎大家提出更好的思路)
我們先定義下基本的html結構
<!--一個post當作一個單位--> <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設定
.image-bg{ background: #e1e1e1; } img { width:100%; opacity: 0; transition: opacity .2s ease-in .25s; } .loaded img { opacity: 1; }
圖片預設是透明度為0,當載入完成後設定為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>實作類別似Pinterest 的圖片預先載入功能</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" href="//cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css" /> <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="//s1.vued.vanthink.cn/jquery-1.10.2.min.js"></script></head><body class="doc"> <h1>實作類別似Pinterest 的圖片預先載入功能</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>
設定背景的顏色
如果你用photoshop開啟一張圖片的話,你只需要幾步就可以確定你希望得到的顏色: 濾鏡 -> 模糊 -> 平均即可。
當然這是針對你所能處理的圖片,如果面對海量的圖片的話,這個時候我們需要用程式去實現。
尋找到一張圖片較為明顯的顏色,需要在三維空間中找到一些彙總的點。如果自己寫的話,需要去瞭解一些彙總演算法。當然自己並不打算去寫更多的內容關於如何去進行圖片的這些顏色的產生,這恐怕不是一篇文章能給說完的。實際上你安裝ImageMagick
就可以簡單的實現預期效果:
convert path/or/url/to/image.png -resize 1x1 txt:-
但是這個不太適合我們寫程式的。我們可以使用第三方的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)); });
運行輸出效果如下:
~ node gm.js./demo1.png:<Buffer 34 29 3b> ./demo2.png:<Buffer cf c3 ad>
對比圖如下:
因此藉助程式,我們可以在儲存圖片的時候進行顏色採集,代碼中通過先將圖片進行大小調整,實際是出於效能的考慮。有助於節約運算時間。除此之外embed.ly也開放了對應的API,方便你擷取網狀圖片的主要色彩。
如果我們能夠有途徑擷取這樣的顏色的話,自然整體功能就沒有什麼難度了。
擴充
其實除了純粹的顏色背景外,我們還可能會遇到類似 medium 的圖片(參考上圖)預先載入技術,才開始圖片是模糊的。實際上我們可以通過外掛程式產生一張幾素的小圖片,然後運用上高四模糊濾鏡,然後等待原圖載入完畢後,我們在顯示原來的圖片。
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" />
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的協助,如果有疑問大家可以留言交流。