JavaScript模仿Pinterest实现图片预加载功能


Posted in Javascript onOctober 25, 2016

前言

对于Pinterest网站,从前端设计出发的话,我们一定不会忘记我们曾经非常流行的瀑布流布局。但是今天,给大家简要分析下 Pinterest上另外一项非常值得借鉴图片加载细节。

看看下面的截图:

JavaScript模仿Pinterest实现图片预加载功能

大家可以感觉到图片出来的时候预先绘制轮廓,重点是预制区域的颜色采用与图片较为相似的色彩值,当图片加载完全后,会有种渐入的效果。

其中谷歌的图片搜索也用到了类似效果:

JavaScript模仿Pinterest实现图片预加载功能

我们称之为这种效果为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打开一张图片的话,你只需要几步就可以确定你希望得到的颜色: 滤镜 -> 模糊 -> 平均即可。

JavaScript模仿Pinterest实现图片预加载功能

当然这是针对你所能处理的图片,如果面对海量的图片的话,这个时候我们需要用程序去实现。

寻找到一张图片较为明显的颜色,需要在三维空间中找到一些聚合的点。如果自己写的话,需要去了解一些聚合算法。当然自己并不打算去写更多的内容关于如何去进行图片的这些颜色的生成,这恐怕不是一篇文章能给说完的。实际上你安装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>

对比图如下:

JavaScript模仿Pinterest实现图片预加载功能

因此借助程序,我们可以在保存图片的时候进行颜色采集,代码中通过先将图片进行大小调整,实际是出于性能的考虑。有助于节约运算时间。除此之外embed.ly也开放了对应的API,方便你获取网络图片的主要色彩。

如果我们能够有途径获取这样的颜色的话,自然整体功能就没有什么难度了。

扩展

JavaScript模仿Pinterest实现图片预加载功能

其实除了纯粹的颜色背景外,我们还可能会遇到类似 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" />

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
大家未必知道的Js技巧收藏
Apr 07 Javascript
jQuery中before()方法用法实例
Dec 25 Javascript
jQuery内部原理和实现方式浅析
Feb 03 Javascript
jQuery选择器及jquery案例详解(必看)
May 20 Javascript
jQuery unbind 删除绑定事件详解
May 24 Javascript
JavaScript实现时间表动态效果
Jul 15 Javascript
JavaScript面向对象精要(下部)
Sep 12 Javascript
vue的全局变量和全局拦截请求器的示例代码
Sep 13 Javascript
JavaScript动态添加数据到表单并提交的几种方式
Jun 26 Javascript
详解基于Wepy开发小程序插件(推荐)
Aug 01 Javascript
vue+canvas实现移动端手写签名
May 21 Javascript
微信小程序中data-key属性之数据传输(经验总结)
Aug 22 Javascript
微信小程序 video组件详解
Oct 25 #Javascript
微信小程序 form组件详解
Oct 25 #Javascript
微信小程序 icon组件详细及实例代码
Oct 25 #Javascript
js 提交form表单和设置form表单请求路径的实现方法
Oct 25 #Javascript
微信小程序  网络请求API详解
Oct 25 #Javascript
微信小程序 progress组件详解及实例代码
Oct 25 #Javascript
微信小程序 swiper组件详解及实例代码
Oct 25 #Javascript
You might like
PHP如何实现跨域
2016/05/30 PHP
Yii CGridView用法实例详解
2016/07/12 PHP
PHP多维数组指定多字段排序的示例代码
2018/05/16 PHP
javascript 循环调用示例介绍
2013/11/20 Javascript
JS文本获得焦点清除文本文字的示例代码
2014/01/13 Javascript
jQuery实现单击和鼠标感应事件
2015/02/01 Javascript
JavaScript让网页出现渐隐渐显背景颜色的方法
2015/04/21 Javascript
纯CSS3代码实现滑动开关效果
2015/08/19 Javascript
Javascript删除指定元素节点的方法
2016/06/21 Javascript
JS实现n秒后自动跳转的两种方法
2020/11/30 Javascript
微信js-sdk界面操作接口用法示例
2016/10/12 Javascript
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
2017/09/18 Javascript
利用JS动态生成隔行换色HTML表格的两种方法
2018/10/09 Javascript
简化版的vue-router实现思路详解
2018/10/19 Javascript
一份超级详细的Vue-cli3.0使用教程【推荐】
2018/11/15 Javascript
vue全局自定义指令-元素拖拽的实现代码
2019/04/14 Javascript
jQuery实现条件搜索查询、实时取值及升降序排序的方法分析
2019/05/04 jQuery
jQuery实现简单QQ聊天框
2020/08/27 jQuery
JavaScript事件循环及宏任务微任务原理解析
2020/09/02 Javascript
python类和函数中使用静态变量的方法
2015/05/09 Python
python使用pymysql实现操作mysql
2016/09/13 Python
python负载均衡的简单实现方法
2018/02/04 Python
详解python配置虚拟环境
2019/04/08 Python
python虚拟环境完美部署教程
2019/08/06 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
Pycharm修改python路径过程图解
2020/05/22 Python
详解css3 mask遮罩实现一些特效
2018/10/24 HTML / CSS
贝尔帐篷精品店:Bell Tent Boutique
2019/06/12 全球购物
德国户外装备、登山运动和攀岩商店:tapir store
2020/02/12 全球购物
NHL官方在线商店:Shop.NHL.com
2020/05/01 全球购物
写自荐信有哪些不宜?
2013/10/17 职场文书
工程管理造价应届生求职信
2013/11/13 职场文书
十佳家长事迹材料
2014/08/26 职场文书
领导干部群众路线教育实践活动剖析材料
2014/10/10 职场文书
祝酒词范文
2015/08/12 职场文书
JavaWeb 入门篇(3)ServletContext 详解 具体应用
2021/07/16 Java/Android