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 相关文章推荐
制作特殊字的脚本
Jun 26 Javascript
Prototype使用指南之string.js
Jan 10 Javascript
js实现的网站首页随机公告随机公告
Mar 14 Javascript
深入学习jQuery Validate表单验证(二)
Jan 18 Javascript
整理AngularJS框架使用过程当中的一些性能优化要点
Mar 05 Javascript
分享JS代码实现鼠标放在输入框上输入框和图片同时更换样式
Sep 01 Javascript
轻松实现jquery选项卡切换效果
Oct 10 Javascript
通过封装scroll.js 获取滚动条的值
Jul 13 Javascript
Vue与Node.js通过socket.io通信的示例代码
Jul 25 Javascript
微信小程序一周时间表功能实现
Oct 17 Javascript
原生jQuery实现只显示年份下拉框
Dec 24 jQuery
js中实现继承的五种方法
Jan 25 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设计模式之结构模式的深入解析
2013/06/13 PHP
基于php中使用excel的简单介绍
2013/08/02 PHP
php生成图片验证码-附五种验证码
2015/08/19 PHP
PHP闭包函数传参及使用外部变量的方法
2016/03/15 PHP
PHP7扩展开发教程之Hello World实现方法示例
2017/08/03 PHP
优化JavaScript脚本的性能的几个注意事项
2006/12/22 Javascript
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
hover的用法及live的用法介绍(鼠标悬停效果)
2013/03/29 Javascript
Jquery网页出现的乱码问题的三种解决方法
2013/06/30 Javascript
使用JavaScript进行进制转换将字符串转换为十进制
2014/09/21 Javascript
重写document.write实现无阻塞加载js广告(补充)
2014/12/12 Javascript
Jquery全选与反选点击执行一次的解决方案
2015/08/14 Javascript
jQuery Easyui 验证两次密码输入是否相等
2016/05/13 Javascript
js canvas实现QQ拨打电话特效
2017/05/10 Javascript
vue小图标favicon不显示的解决方案
2017/09/19 Javascript
web前端vue之CSS过渡效果示例
2018/01/10 Javascript
vue.js层叠轮播效果的实例代码
2018/11/08 Javascript
ant-design-vue中tree增删改的操作方法
2020/11/03 Javascript
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
Python通过RabbitMQ服务器实现交换机功能的实例教程
2016/06/29 Python
python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE方法
2017/05/24 Python
Python数据结构与算法之图的广度优先与深度优先搜索算法示例
2017/12/14 Python
python爬取淘宝商品详情页数据
2018/02/23 Python
Python之文字转图片方法
2018/05/10 Python
啥是佩奇?使用Python自动绘画小猪佩奇的代码实例
2019/02/20 Python
Python中使用遍历在列表中添加字典遇到的坑
2019/02/27 Python
通过PHP与Python代码对比的语法差异详解
2019/07/10 Python
python如何处理程序无法打开
2020/06/16 Python
巧用CSS3 border实现图片遮罩效果代码
2012/04/09 HTML / CSS
HTML5 video播放器全屏(fullScreen)方法实例
2015/04/24 HTML / CSS
一些Unix笔试题和面试题
2012/09/25 面试题
医院检讨书范文
2014/02/01 职场文书
双创工作实施方案
2014/03/26 职场文书
教师演讲稿大全
2014/05/16 职场文书
初中中等生评语
2014/12/29 职场文书
新店开业策划方案怎么书写?
2019/07/05 职场文书