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 相关文章推荐
统一接口:为FireFox添加IE的方法和属性的js代码
Mar 25 Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
Nov 14 Javascript
类似天猫商品详情随浏览器移动的示例代码
Feb 27 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
Web打印解决方案之证件套打的实现思路
Aug 29 Javascript
js实现图片上传预览原理分析
Jul 13 Javascript
JS中Promise函数then的奥秘探究
Jul 30 Javascript
在vue.js中使用JSZip实现在前端解压文件的方法
Sep 05 Javascript
利用jqgrid实现上移下移单元格功能
Nov 07 Javascript
微信小程序结合mock.js实现后台模拟及调试
Mar 28 Javascript
jQuery Datatables 动态列+跨列合并实现代码
Jan 30 jQuery
vue实现拖拽交换位置
Apr 07 Vue.js
微信小程序 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
【动漫杂谈】关于《请在T台上微笑》
2020/03/03 日漫
php遍历数组的方法分享
2012/03/22 PHP
php程序总是提示验证码输入有误解决方案
2015/01/07 PHP
php微信开发之带参数二维码的使用
2016/08/03 PHP
PHP使用curl_multi实现并发请求的方法示例
2018/04/29 PHP
火狐textarea输入法的bug的触发及解决
2013/07/24 Javascript
javascript删除数组元素并且数组长度减小的简单实例
2014/02/14 Javascript
Javascript正则控制文本框只能输入整数或浮点数
2014/09/02 Javascript
解决ueditor jquery javascript 取值问题
2014/12/30 Javascript
探析浏览器执行JavaScript脚本加载与代码执行顺序
2016/01/12 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
javascript 作用于作用域链的详解
2017/09/27 Javascript
Vue使用vue-area-linkage实现地址三级联动效果的示例
2018/06/27 Javascript
代码分析vue中如何配置less
2018/09/28 Javascript
vue使用echarts图表的详细方法
2018/10/22 Javascript
vue分页器组件编写方法详解
2019/06/28 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
如何在postman中添加cookie信息步骤解析
2020/06/30 Javascript
[02:36]DOTA2英雄基础教程 斯拉克
2013/11/29 DOTA
Python抓取百度查询结果的方法
2015/07/08 Python
python如何通过protobuf实现rpc
2016/03/06 Python
详解Python中的array数组模块相关使用
2016/07/05 Python
tensorflow创建变量以及根据名称查找变量
2018/03/10 Python
win10 64bit下python NLTK安装教程
2018/09/19 Python
对pytorch的函数中的group参数的作用介绍
2020/02/18 Python
来自美国主售篮球鞋的零售商店:KICKSUSA
2017/11/28 全球购物
优秀中专生推荐信
2013/11/17 职场文书
物理专业大学生职业生涯规划书
2014/02/07 职场文书
服装设计专业自荐信
2014/06/17 职场文书
《我爱祖国》演讲稿1000字
2014/09/26 职场文书
信息技术教研组工作总结
2015/08/13 职场文书
周一早安温馨问候祝福语!
2019/07/15 职场文书
浅谈vue2的$refs在vue3组合式API中的替代方法
2021/04/18 Vue.js
关于 Python json中load和loads区别
2021/11/07 Python
日元符号 ¥
2022/02/17 杂记
《模拟人生4》推出新补丁 “婚礼奇缘”DLC终于得到修复
2022/04/03 其他游戏