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 相关文章推荐
JavaScript Accessor实现说明
Dec 06 Javascript
JS中 用户登录系统的解决办法
Apr 15 Javascript
函数式 JavaScript(一)简介
Jul 07 Javascript
jQuery支持动态参数将函数绑定到事件上的方法
Mar 17 Javascript
AngularJS基础 ng-model 指令详解及示例代码
Aug 02 Javascript
Vue.js中数组变动的检测详解
Oct 12 Javascript
微信小程序 省市区选择器实例详解(附源码下载)
Jan 05 Javascript
详解浏览器渲染页面过程
Feb 09 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
Aug 31 Javascript
echarts实现地图定时切换散点与多图表级联联动详解
Aug 07 Javascript
jQuery easyui datagird编辑行删除行功能的实现代码
Sep 20 jQuery
Vue实现仿iPhone悬浮球的示例代码
Mar 13 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下通过POST还是GET来传值
2008/06/05 PHP
php静态文件返回304技巧分享
2015/01/06 PHP
详解将数据从Laravel传送到vue的四种方式
2019/10/16 PHP
jquery text()方法取标签中的文本
2014/07/25 Javascript
NodeJS和BootStrap分页效果的实现代码
2016/11/07 NodeJs
微信小程序遇到修改数据后页面不渲染的问题解决
2017/03/09 Javascript
使用命令行工具npm新创建一个vue项目的方法
2017/12/27 Javascript
JS设计模式之策略模式概念与用法分析
2018/02/05 Javascript
微信小程序实现动态显示和隐藏某个控件功能示例
2018/12/14 Javascript
详解Vue中组件传值的多重实现方式
2019/08/16 Javascript
vscode 调试 node.js的方法步骤
2020/09/15 Javascript
[01:29]Ti4循环赛第三日精彩回顾
2014/07/13 DOTA
[01:14]英雄,所敬略同——2018完美盛典宣传视频
2018/12/05 DOTA
树莓派中python获取GY-85九轴模块信息示例
2013/12/05 Python
wxPython框架类和面板类的使用实例
2014/09/28 Python
在Python中执行系统命令的方法示例详解
2017/09/14 Python
Python OpenCV中的resize()函数的使用
2019/06/20 Python
Python自动化导出zabbix数据并发邮件脚本
2019/08/16 Python
python 实现二维字典的键值合并等函数
2019/12/06 Python
python实现秒杀商品的微信自动提醒功能(代码详解)
2020/04/27 Python
Stuart Weitzman欧盟:美国奢华鞋履品牌
2017/05/24 全球购物
优秀毕业大学生推荐信
2013/11/13 职场文书
水污染治理专业毕业生推荐信
2013/11/14 职场文书
仓库理货员岗位职责
2013/12/18 职场文书
高一数学教学反思
2014/02/07 职场文书
挂科检讨书范文
2014/02/20 职场文书
法律进学校实施方案
2014/03/15 职场文书
教师业务培训方案
2014/05/01 职场文书
卫生系统先进事迹
2014/05/13 职场文书
党建工作目标管理责任书
2015/01/29 职场文书
高一军训决心书
2015/02/05 职场文书
关于倡议书的范文
2015/04/29 职场文书
党员转正意见怎么写
2015/06/03 职场文书
提档介绍信范文
2015/10/22 职场文书
2015年教师个人业务工作总结
2015/10/23 职场文书
python开发人人对战的五子棋小游戏
2022/05/02 Python