YIXUNFE / blog

文章区
151 stars 25 forks source link

响应式图片 #25

Open yvesluo opened 8 years ago

yvesluo commented 8 years ago

什么是响应式图片?

响应式图片关键之一就是让浏览器能够自动调节图片尺寸。   为了能自动调节图片尺寸,就需要准备大尺寸图片。一些网站为了适应高清屏设备的要求,都需要准备超大大尺寸图片,例如:   http://www.w3cplus.com/sites/default/files/blogs/2015/1509/hero_ygold_edition_large_2x.jpg

  此图尺寸:5144px x 1698px,体积是398K。   问题:把这样一张尺寸过大的图片传送到一些低分辨率设备上,会造成资源浪费。

什么情况下需要使用到响应式图片?

  一般情况下,需要使用到响应式图片的情况有两种:分辨率切换和艺术指导,以下分别详细说明:  

分辨率切换:硬式切换

  最常见的情况,不改变图片高宽比的情况下显示不同尺寸,这个很好理解  

艺术切换:软式切换

很多情况下,设计师和产品会要求在尺寸改变的同时,改变图片的高宽比,以达到修改图片的内容,聚焦点等等。这种情况主要是为了迎合人类主观视感受的要求。我们把这种情况称为艺术指导,或相对于分辨率切换:硬式切换,也可以称之为软式切换。

当照片以大尺寸显示时,显示出背景里的汽车工厂是有意义的。背景可以在图像上说明这个事件发生的地点。然而试想如果我们把图片缩小来适应小屏幕的时候呢? 照片被缩放到宽度为100px。

  在这个尺寸上,你无法辨认出人物的脸部,背景更是一片模糊。因此,我们不应该简单得缩放图片,而应该合理裁切图片, 去掉一些背景从而把焦点放到奥巴马身上。最终结果这张图片在小尺寸上的表现变得更好。

来看一下更加复杂的例子:   最常见的场景是图文并茂的设计  

这个图像包含了三个照片,两个带有文字的logo,一个描边邮戳和文本。如果我们只是简单粗暴地把这个图像调整到320px宽,文本将会变得太小而无法辨认。  

更理想的结果是这样的:

响应式图片解决方案

响应式图片解决方案,最经典的有元素,其它比较新近的例如和srcset,等,不管采用哪种方案,元素必不可少。  

img 的currentsrc属性

方法:用JavaScript来监控img元素上currentSrc的变化

来看一个例子  

(function() {
  var currentSrc, oldSrc, imgEl;
  var showPicSrc = function() {
    oldSrc     = currentSrc;
    imgEl      = document.getElementById('picimg');
    currentSrc = imgEl.currentSrc || imgEl.src;
    if (typeof oldSrc === 'undefined' || oldSrc !== currentSrc) {
      document.getElementById('logger').innerHTML = currentSrc;
    }
  };
  // You may wish to debounce resize if you have performance concerns
  window.addEventListener('resize', showPicSrc);
  window.addEventListener('load', showPicSrc);
})(window);

  在示例中,你可以改变浏览器尺寸来观察currentsrc的变化。将你的浏览器慢慢的缩小,你将看到如下图的一个变化效果:

其它更强大的方法,比如说想要支持高分辨率屏幕,我们需要扩展元素。

SRCSET

  自从苹果发布带retina显示屏的iPhone 4,网页设计人员一直在找一个处理高分屏的方案。于是引入了srcset和它的显示密度。  

srcset密度描述

语法:在元素上添加srcset属性。srcset的值是一个用逗号分隔的列表。列表中的每个项包含一张图片的路径并且按倍数(例如,1x,2x,3x...)提供多张分辨率的图片

image

问题: 1x,1.5x,2x,3x !!!! 我们需要为多种像素密度提供相应的设置吗?好难维护!!!

 

Srcset宽度描述

语法与屏幕密度描述符类似。srcset属性值是逗号分隔的图片源和描述列表。区别是我们在这边列出了图片源宽度。

image

问题:当图片开始下载时浏览器知道的只有视窗尺寸  

SRCSET密度描述和宽度描述结合

也有人提到混合SRCSETSRCSET结合显示密度描述和宽度描述的方法,在CHROME模拟器上测试失效  

智能的srcset和sizes属性

以上写法都会有各种问题,最新的建议SRCSET写法是这样子的:   image

非常方便:只需要提供图片资源、以及断点,其他都交给浏览器智能解决,什么响应宽度啊、设备像素比啊,都不要关心了,浏览器会自动匹配最佳显示图片。   例:

<img src="kebile-s.jpg" srcset="kebile-s.jpg 320w, kebile-m.jpg 640w, kebile.jpg 1280w"
         sizes="(max-width: 480px) 100vw, (max-width: 900px) 50vw, 900px">

  上面的例子提供了三种尺寸的图片源,SIZES设置的意思是:指定三种BREAKPOINT,屏幕小于480时图片WIDTH=100%, 481-900时图片WIDTH=50%,然后是901之后图片永远是显示900PX。   100vw是指图片的宽度值设置,1vw等于 1%,33vw就是33%,当然也可以使用其它的单位,em, px, cm, vw, 等等,甚至可以用CSS3的calc计算,例如:sizes="(max-width: 360px) calc(100vw - 20px), 128px"。

PICTURE标签

之前的内容都是针对“分辨率切换”的使用情况来进行的讨论。下面来讨论一下怎么应对“艺术指导”的情况。这就需要用到元素。   image

元素包含一系列子元素后跟着需要的元素。source元素和video元素的子源类似。 每个源必须有一个srcset属性,可选属性包括media,sizes和type。元素上的sizes和srcset的使用和上完全一样。   MEDIA:media属性的值就是我们熟悉的媒体查询。如果没有匹配媒体查询时,浏览器则使用元素。 SRCSET:与的srcset不同,的srcset,前者不是建议,而是指令。此时浏览器必须使用srcset指定的图片。   ## 来个实战的例子:[http://www.shopify.com/](http://www.shopify.com/) ![](http://cdn2.w3cplus.com/cdn/farfuture/YV-of2hWhxbru9QVlRNn3HIbr2UVrla5mGgYSNtJ7wA/mtime:1444396279/sites/default/files/blogs/2015/1510/shopify-picture-example3.gif)   注意人物部分的图片切换。   以下是简化后图片部分的代码 ``` html Shopify Merchant, Corrine Anestopoulos ```   ## Type属性 给大家带来的另一个好处就是,提供了浏览器对图片格式进行自由选择的机制。 ![](http://cdn.w3cplus.com/cdn/farfuture/w5rVZSZXm1ZG97gewS5rlNrSnLi3siu9VKw29FdIa1A/mtime:1443922552/sites/default/files/blogs/2015/1510/picture-type.png) 通过type属性,我们不仅可以使用经典的gif, jpg, png图片格式,还可以指定使用比较新潮的svg或webp。如: ``` html  ACME Corp ``` 在这个例子中,如果浏览器能够识别SVG,则使用SVG,如果不行,就往下类推,最后旧版本的浏览器使用logo.png。   到这里我们可以发现,我们在这边实现了在图片格式使用上的渐进增强的功能,在使用SVG文件的同时,我们又兼顾了旧版本浏览器用户的体验,从而防止的用户流失。   另外一点需要注意的是,TYPE,SIZES和 SCRSET是可以自由组合来完成不同的功能。   # CSS实现响应式图片   上面我们讨论的是使用内联图片来实现响应式图片,接着我们来看使用CSS实现响应式图片的方法。说到CSS,响应式,有的同学会马上想到媒体查询。在和srcset的解决方案出现之前,我们一直都用CSS媒体查询实现响应式功能,现在来看一下,在CSS方面,内联图片响应式为我们带来什么新的启发。 ## image-set()语法 ![](http://cdn.w3cplus.com/cdn/farfuture/Pmo2T2__0yf-BvWLggP6tcZV1S7gmxI5pglLK-_1ks8/mtime:1444135819/sites/default/files/blogs/2015/1510/image-set.png) 我们会注意到image-set()和srcset之间的一些联系。需要注意的是image-set不支持宽度描述。   Image-set可以用在任何可以使用图片的CSS属性上。   ## 分辨率媒体查询 ![](http://cdn.w3cplus.com/cdn/farfuture/oTVTtOZdGn7pvw8zE2ZzjFSjq6ww0lD2wAPVPradpuI/mtime:1444135819/sites/default/files/blogs/2015/1510/resolution-mq.png) 首先会注意到的是我们加入了包含-webkit前缀的媒体查询。这是为了支持老device-pixel-ratio语法的机器。只有一台机器支持这个带-webkit前缀的语法所以只列出了一台。   现在的设备都支持min-resolution和max-resolution, 可以使用以下单位   dpi:点每英尺 dpcm:点每厘米 dppx:点每像素, 这个单位可以基本理解为等于x, 1dppx = 1x, 2 dppx = 2x # 兼容性   响应式图片标准的浏览器支持在快速发展。到2015年8月,Chrome,Opera和Firefox都支持了 picture, srcset, sizes, 和type.   Microsoft Edge和Safari支持带有显示描述符(x)的srcset,但不支持宽度描述符。Microsoft已经开始了支持所有响应式图片标准的开发。   image-set()相对落后。   ## SCRSET http://caniuse.com/#search=srcset ## PICTURE http://caniuse.com/#search=picture ## PictureFill   PictureFill插件让你现在就可以使用新响应式图片语法。 https://scottjehl.github.io/picturefill/ # 响应式图片断点   响应式图片的断点设置是个很复杂的问题。要比较完美的设置断点需要考虑多方面的因素,我们这边就不做过多详解。但是我们设置断点时需要永远记住,响应式图片断点要解决的问题是:   需要提供多少个图片源来包含此图片需要使用的场景? 在哪里以及什么时候应该使用这些图片? 以这两个问题为出发点来思考解决方案,这样一切问题应该可以迎刃而解。 由于文章篇幅限制,关于响应式图片我们就讨论到这里,需要做更多了解的同学可以参考以下文章。   参考: http://blog.cloudfour.com/responsive-images-101-definitions/ 译文:http://www.w3cplus.com/responsive/responsive-images-101-definitions.html   http://www.zhangxinxu.com/wordpress/2014/10/responsive-images-srcset-size-w-descriptor/