如何对移动端的图片流量进行优化

刷新一个页面消耗的流量除了脚本样式文件以外,大头其实在下载的图片。一张图片动辄几十kb,想尽办法优化样式、脚本文件所优化的图片流量其实还不如一张图片大。

本文从两个角度介绍如何对图片流量进行优化。本文进行图片流量优化的前提都是对于移动端而言。

webp

首先从图片格式方面着手,webp(google官方网址)是谷歌推出的一种图片格式,优点在于同等画面质量下,体积比jpg、png少了25%以上。以两张jpg、png图片为例:

  1. JPG http://cdn1.showjoy.com/images/c9/c9c2221942774550ad53342da23774de.jpg
  2. PNG http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png
size JPG PNG
无压缩 165kb 55kb
tinypng压缩 75kb 20kb
webp转换 54kb 6.1kb

由表格的罗列可知,将图片转换为webp格式,图片的体积比tinypng压缩完后的体积还要小,且图片质量甚至还要高于tinypng压缩。

虽然webp格式的图片相对于png和jpg体积小质量高,但是目前的兼容性在全球范围只达到了70%左右。(caniuse截止20160911)

根据caniuse,目前在移动端安卓机型4.4以上全部支持,但是ios全军覆灭。我司用户ios、安卓55分成,支持了webp至少能为一半用户提供更小体积的图片体验。而且据说ios10系统将支持webp,这样一来我司产品的webp支持度将会更高。ios10有望支持webp

图片服务器支持webp转换

我司原本就有基于nginx+lua+graphicsmagick的图片缩略图功能,具体使用方法类似

http://cdn1.shwojoy.com/images/34/xxxxx.png

http://cdn1.shwojoy.com/images/34/xxxxx.png.300x300.png

为了支持webp转换需要修改原先的lua脚本,添加对.webp后缀的识别。使之能对类似xxxxx.png.300x300.png.webp或者xxxxx.png.webp这样的域名进行识别并转换。

nginx+lua+graphicsmagick这套方案其实做的事情就是nginx对域名进行拦截,lua脚本进行域名后缀规则的匹配,比如说300x300.png/.webp类似的后缀,匹配完成后再在lua里调用graphicsmagick的命令,进行一些图片转换、裁剪等工作。

lua脚本片段


  1. if table.isLegal(size_list) and extend == "webp" then 
  2.         command = [[/usr/local/GraphicsMagick-1.3.25/bin/gm convert -quality 75 -density 72 +profile "*"  ]] .. ngx.var.image_root ..  originalUri  .. " -geometry " .. area .. " " .. ngx.var.file; 
  3.         os.execute(command); 
  4. end 

值得注意的是graphicsmagick版本在1.3.20及以上才支持webp download

graphicsmagick能做到转换webp还需要下载编译libwebp。graphicsmagick支持webp教程

图片服务器支持webp转换后,就能实时转化webp格式的图片了,为接下来的webp兼容方案提供了技术支持。

  • http://cdn1.showjoy.com/images/c9/c9c2221942774550ad53342da23774de.jpg
  • http://cdn1.showjoy.com/images/c9/c9c2221942774550ad53342da23774de.jpg.webp

webp兼容方案

目前在浏览器端判断是否支持webp最好的方法就是特性检测法。根据检测结果将是否支持webp的值存入cookie,供之后需要判断webp兼容性的地方使用。

特性检测脚本:(参考)


  1. ;(function(doc) { 
  2.     // 给html根节点加上webps类名 
  3.     function addRootTag() { 
  4.         doc.documentElement.className += " webpa"; 
  5.     } 
  6.  
  7.     // 判断是否有webp_showjoy=available这个cookie 
  8.     if (!/webp_showjoy=available/.test(document.cookie)) { 
  9.         var image = new Image(); 
  10.  
  11.         // 图片加载完成时候的操作 
  12.         image.onload = function() { 
  13.  
  14.             // 图片加载成功且宽度为1,那么就代表支持webp了,因为这张base64图是webp格式。如果不支持会触发image.error方法 
  15.             if (image.width == 1) { 
  16.  
  17.                 // html根节点添加class,并且埋入cookie 
  18.                 addRootTag(); 
  19.                 document.cookie = "webp_showjoy=available; max-age=31536000; domain="; 
  20.             } 
  21.         }; 
  22.  
  23.         // 一张支持alpha透明度的webp的图片,使用base64编码 
  24.         image.src = 'data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA=='; 
  25.     } else { 
  26.         addRootTag(); 
  27.     } 
  28. }(document));  

如果浏览器支持webp格式的图片则在cookie中设置标志,并且在html标签上设置webpaclassName,这个classname的作用是在less文件中兼容webp图片。

less文件中的webp兼容


  1. .webpbg(@url) { 
  2.   background-image: url(@url); 
  3.   .webpa & { 
  4.     background-image: url('@{url}.webp'); 
  5.   } 
  6. }  

这段less取代了原先在less文件中描述背景图片的代码。

比如原先定义背景图片


  1. div { 
  2.     background-image: url(xx); 
  3. }  

现在使用兼容方案则为:


  1. div { 
  2.     webpbg(xxx); 
  3. }  

html文件中的webp图片兼容

我司目前html部分通过java的velocity编写,对于同步传递到页面上的图片webp将通过如下方式兼容。


  1. <img class="slider-img" src="$!{banner.recordMap.get('图片地址').value}.750x448.jpg$!{isWebp}"> 

$!{isWebp} 变量是后台通过判断浏览器请求的cookie中是否有之前定义的webp_showjoy=available,有则返回.webp后缀,无则返回空。

这样有个问题是用户第一次浏览产品页面时后台判断cookie永远是false,所以用户第一次浏览是不可能返回.webp后缀的图片的。

还有一种情况是图片大量使用的时候我们会使用懒加载进行图片的延迟加载。这时就可以修改懒加载插件,在插件里动态兼容webp图片了。


  1. /* 根据cookie返回图片是否webp的地址 */ 
  2. function getwebpsrc (imgsrc) { 
  3.     var needwebp = false, 
  4.         src = ''; 
  5.     if (/webp_showjoy=available/.test(document.cookie)) { 
  6.         needwebp = true; 
  7.     } 
  8.     src = needwebp ? imgsrc + '.webp' : imgsrc; 
  9.     return src; 
  10. }  

到此就完成了移动端对webp格式图片的支持。这也是图片流量优化其中之一方案。

retina兼容图片流量优化

前端应该都了解在retina屏下应该使用@2x或者@3x等倍率的图片,才能保证图片的清晰度。但是为了切图方便,部分公司都会统一在切图阶段切出@2x的图片,不管浏览设备是retina屏还是普通屏,一律都使用@2x的图片。这样做有两个坏处,一是@2x的图片在非retina屏下会出现downsampled现象,虽然不会影响清晰度,但是会缺少一些锐利度。二是@2x的图片相比较@1x的图片,前者体积大于后者,这也就造成了流量的浪费以及影响页面打开性能。

所以正确处理方法是针对retina屏的是否采用不同尺寸的图片。图片裁剪已经在图片服务器上实现。在考虑retina时也需要加上webp的兼容,两者一起作用会大大减少图片的尺寸。


  1. @2x http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png.300x300.png.webp 
  2. @1x http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png.150x150.png.webp  

less文件兼容retina


  1. .retinabg(@file-2x; @reg-2x; @reg-1x; @type) when (isstring(@reg-2x)) { 
  2.  
  3.   background-image: url("@{file-2x}.@{reg-1x}.@{type}"); 
  4.   .webpa & { 
  5.     background-image: url('@{file-2x}.@{reg-1x}.@{type}.webp'); 
  6.   } 
  7.   @media 
  8.   only screen and (-webkit-min-device-pixel-ratio: 2), 
  9.   only screen and (   min--moz-device-pixel-ratio: 2), 
  10.   only screen and (     -o-min-device-pixel-ratio: 2/1), 
  11.   only screen and (        min-device-pixel-ratio: 2), 
  12.   only screen and (                min-resolution: 192dpi), 
  13.   only screen and (                min-resolution: 2dppx) { 
  14.     background-image: url("@{file-2x}.@{reg-2x}.@{type}"); 
  15.     .webpa & { 
  16.       background-image: url('@{file-2x}.@{reg-2x}.@{type}.webp'); 
  17.     } 
  18.   } 
  19. }  

当要代替原先书写时的background-image: url(),可以写成如下方式:


  1. .retinabg(http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png; 300x300; 150x150; png) 

html文件兼容retina

在html中本次方案准备使用html5特性srcset属性。

secset属性的目的在于允许开发者为某个图片的属性指定一系列的来源,其中这些图片的来源是要根据客户端显示屏的像素分辨率来设定的。

比如在volecity模板中定义图片资源:


  1. <img class="pic" src="$!{newProduct.image}.300x300.png$!{isWebp}" srcset="$!{newProduct.image}.150x150.png$!{isWebp} 1x, $!{newProduct.image}.300x300.png$!{isWebp} 2x"> 

这段图片定义说明了在retina(2x)屏幕下使用300x300的图片来源,而在飞retina屏下(1x)下使用150x150的图。

html中懒加载的图片

由于懒加载的图片在插件中就会进行src赋值的操作,所以直接在懒加载插件中根据window.devicePixelRatio进行判断修改图片url。


  1. /* 根据cookie返回图片是否webp的地址 */ 
  2. /* 根据dpr返回不同尺寸的图片 */ 
  3. function getwebpsrc (imgsrc) { 
  4.     var areaInfo = ''; 
  5.     if (window.devicePixelRatio && window.devicePixelRatio <= 1) { 
  6.         var area = imgsrc.match(/[0-9]+x[0-9]+/); 
  7.         if (area) { 
  8.             var areaSplit = area[0].split('x'); 
  9.             areaInfo = areaSplit[0] /2 + 'x' + areaSplit[1] /2; 
  10.             imgsrc = imgsrc.replace(/[0-9]+x[0-9]+/, areaInfo) 
  11.         } 
  12.     } 
  13.     var needwebp = false, 
  14.         src = ''; 
  15.     if (/webp_showjoy=available/.test(document.cookie)) { 
  16.         needwebp = true; 
  17.     } 
  18.     src = needwebp ? imgsrc + '.webp' : imgsrc; 
  19.     return src; 
  20. }  

在这个方案下所有图片的编写都必须要带上尺寸后缀(_num_x_num_),在我司图片服务器支持下还有一个特别的好处:图片服务器会对带有尺寸后缀的图片进行尺寸裁剪的同时进行图片压缩,遇到不支持webp格式的浏览器上就会顺带对图片进行压缩,尽力地减小图片体积。

srcset属性目前在移动端的兼容性十分不错,安卓4.x版本不支持。

总结

一共两点图片流量优化方案,一是针对webp图片格式,二是针对retina。最后总结下来的编写图片代码的情景就为3种:

  1. html同步图片编写

  1. <img class="pic" src="$!{newProduct.image}.300x300.png$!{isWebp}" srcset="$!{newProduct.image}.150x150.png$!{isWebp} 1x, $!{newProduct.image}.300x300.png$!{isWebp} 2x"> 

懒加载图片编写


  1. <img class="goods-pic j_Lazyload" data-original="{{$value.image}}.300x300.png"src="http://cdn1.showjoy.com/images/a5/a560e106324d4670acd11b69aee0f11f.png"> 

less


  1. .retinabg(http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png; 300x300; 150x150; png) 
  2.  
  3. webpbg(http://cdn1.showjoy.com/images/bb/bb1c8b0d275e4ba2903dc822a03add50.png); 

作者:lv_DaDa

来源:51CTO

时间: 2024-10-30 01:53:40

如何对移动端的图片流量进行优化的相关文章

为什么要做图片流量优化

摘要: 最近在鼓捣一个图片站的优化,发现人们对图片流量优化的认知还很低,所以就想要把自己看到的一些东西写下来,于是有了这一些列文章吧. 开篇为,为什要做图片流量的优化,很少 最近在鼓捣一个图片站的优化,发现人们对图片流量优化的认知还很低,所以就想要把自己看到的一些东西写下来,于是有了这一些列文章吧. 开篇为,为什要做图片流量的优化,很少有人意识到图片也是能给网站来很多流量,很多流量统计工具没有标识出某些流量是通过图片搜索带来的,可以用光年日志分析工具来查看下日志,里边很清楚的标识了流量的图片来路

wpf-WPF 批量保存FTP端的图片

问题描述 WPF 批量保存FTP端的图片 最近弄一个小程序要保存FTP服务端的图片到本地, 单独的图片的保存弄出来了但是批量的不知道如何下手, 而且要求能弹出保存对话框选择保存地址的那种 解决方案 相当于一格ftp客户端.一般的FTP客户端都是单条的循环模式.当然可以加入多线程的方式. 搜一下ftp客户端http://www.mysjtu.com/page/M0/S807/807351.html 解决方案二: 直接用ftpclient类就可以了.保存对话框用Microsoft.Win32.Sav

android开发-想用socket从服务端发送图片到客户端,但一直出错,求原因

问题描述 想用socket从服务端发送图片到客户端,但一直出错,求原因 开发-想用socket从服务端发送图片到客户端,但一直出错,求原因-socket客户端和服务端"> 如图所示,本人新人,求大神解答 解决方案 空指针从无,TestActivity的64行 解决方案二: 空指针 socket 不能执行关闭操作(其实是不能操作任何操作) 最好在操作前增加判断:if(null != socket) {} 在 {} 中做处理. 解决方案三: 应该是创建socket失败了. socket不能放在

PC_android使用socket通信,要求PC服务端发送图片给手机客户端,并在手机显示

问题描述 PC_android使用socket通信,要求PC服务端发送图片给手机客户端,并在手机显示 本人根据"http://sishuok.com/forum/posts/list/1995.html"此网址,做了一个socket通信的例子,但是通信成功了,图片在手机中显示不出来,求解答 解决方案 http://www.cnblogs.com/tt_mc/archive/2010/06/04/1751260.html 解决方案二: http://blog.csdn.net/tobac

jQuery插件slick实现响应式移动端幻灯片图片切换特效_jquery

jQuery响应式手机端移动端幻灯片图片切换特效插件slick,基于jQuery,功能非常强大,支持左右按钮切换.支持圆点切换.支持自定义切换数量,支持自定义切换速度.支持图片预加载.支持自动播放定义,效果非常的不错,众多的参数自定义支持,觉得可以的可以参考他们的参数配置,还是值得学习使用的. 使用方法: 1.加载插件和jQuery <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> &l

php数据-php后台为android端提供图片,为什么十几张图片就把内存占了30多M

问题描述 php后台为android端提供图片,为什么十几张图片就把内存占了30多M 使用的是ImageLoader 这个开源框架加载图片,我把图片路径添加到它官方下载的源码中 运行也是占了很大的内存,我现在都不知道是我的原因还是后台的原因了,php他们是直接提供原图 1M多一张吧 给我的,好纠结啊.求解 解决方案 一张图1M多,当然要站内存啦,我们一个主题就有几百张图,但是都是压缩的图片,最多一张也就100多k,android那边用的异步加载,毫无压力,原图只能用于单个点击查看

iOS端发送图片消息安卓端点开大图无法显示

问题描述 iOS端获取聊天记录和log日志中,消息的body都是一串字符串,被加密了. 解决方案 iOS端发送消息加密,安卓端无法获取到这个图片的大图,iOS端发送图片消息时不要加密即可.

打造图片流量网站必须巧用的seo要点

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 众所周知,图片网站可以引爆网站的流量,其实呢,最近也一直观察很多流量的网站,发现很多流量网站都具有他们的seo的特色,这篇文章呢,就用一些图片流量的网站所用的seo技巧来述说一下这些流量优化的技巧吧,如果你也想好好做一个图片网站,那么我希望这篇文章可以给你们一些小小建议吧. 第一点:ALT标签的使用 相信很多站长都明白alt属性对于图片的重要

网站图片的搜索引擎优化策略

我以前曾经提到过,网站的图片是非常耗费流量的,去年我就曾经统计过,两天的时间博客有20多G的访问流量,图片所在的目录upload占用了18.6G,而文章所在目录只用了1.3G流量,可见图片占用流量资源之巨大,这也就是很多人都喜欢将图片文件放在第三方免费网络相册的原因. 然而,如果条件允许的话(比如有独立的服务器,充足的流量),那么将图片存储在自己的网站空间,反而可以利用搜索引擎的图片搜索给自己带来不少额外流量,这里的搜索引擎指的是Google的图片搜索,而不是百度,因为百度采用盗链机制,其图片搜