一、什么是响应式图片
随着不同分辨率的移动设备出现,网页需要在不同分辨率的设备下给用户提供更加舒适的体验,随之就出现了响应式布局的概念。
响应式布局是Ethan Marcotte提出来的,说白了就是一个网站能兼容不同分辨率的设备,而无需为每一个分辨率的终端各写一个网页。
其主要用到的技术是CSS3中的Media Query以及为了兼容古董浏览器而生的各种插件。而响应式图片不同,它使用的是javascript和服务器的方式去实现。响应式图标不单单是简单的把IMG元素根据屏幕大小去缩放,而是在一定尺寸的设备中,使用不同分辨率(也就是图片大小)不同的图片。
二、响应式图片的好处
低分辨率的设备大部分都是移动设备,如果在分辨率较低时,让网页去加载对应分辨率较低的图片,不仅会加快网页的呈现速度,而且能节省流量。
三、Responsive-Images
Responsive-Images是一个响应式图片的解决方案,它将在屏幕分辨率小于480px的时候加载小尺寸的图片。源码可以在Github上下载,也可以在这里看到DEMO。
它主要是根据服务器重定向或IMG标签路径替换的方式来实现响应式图片,下面解释一下它的工作原理。
四、使用方法
1.网站所使用的服务器必须是apache
2.将“.htaccess”文件拷贝到apache web 服务器的根文件头中
3.在页面的中导入“responsiveimgs.min.js”
4.
small.jpg表示的是将要加载的小尺寸图片,large.jpg表示将要加载的大尺寸图片。
五、工作原理
下面我们来看看它的源码是怎么工作的。
wideload = win.screen.availWidth > widthBreakPoint;
if( !wideload ){
return;
}
widthBreakPoint的默认值为480,当屏幕的宽度小于480px时,程序返回,不执行后面的代码,默认使用small.jpg。“?full=large.jpg”会被浏览器当作参数扔掉。
当屏幕的宽度大于480px时,继续下面的代码
var base = (function(){
var backup,
baseAdded = false,
a = doc.createElement("a"),
supported = false,
base = head.getElementsByTagName( "base" )[0] || (function(){
baseAdded = true;
return head.insertBefore( doc.createElement("base"), head.firstChild );
})();
backup = !baseAdded && base.href;
//test base support before using
base.href = location.protocol + "//" + "x/";
a.href = "y";
//if dynamic base tag is unsupported (Firefox)
if( a.href.indexOf( "x/y" ) < 0 ){
if( backup ){
base.href = backup;
}
else{
head.removeChild(base);
}
base = null;
}
else{
base.href = dirPath + "rwd-router/";
}
//return
return base;
})()
这段代码看似很长的样子,但是其实很简单,它的功能主要是生成base标签,并加入到标签中,不知道base标签的点这里。
代码中的dirPath是这样来的
filePath = location.href;
dirPath = filePath.substring( 0, filePath.lastIndexOf( "/" ) ) + "/";
如果filePath是"http://filamentgroup.com/examples/responsive-images/xxxx.jpg",则dirPath为"http://filamentgroup.com/examples/responsive-images/"
这段代码执行过后,在标签中生成了这样一个标签:
这是一个虚拟全局路径,点击img后,跳向的是下面这个地址:
"http://filamentgroup.com/examples/responsive-images/rwd-router/small.jpg?full=large.jpg"
紧接着我们要处理这个虚拟的URL了,这时候我们就用到了开头说的 .htaccess 文件。
这个文件是apache服务器的一个分布式配置文件,用于针对自定义规则改变目录的配置方法,简单的来说就是用来重定向的。
现在我们看看这个文件的内容:
RewriteEngine On
# direct image requests to temp
RewriteCond %{QUERY_STRING} full=(.*)&?
RewriteRule (.*)rwd-router/.*\.(jpe?g|png|gif|webp) $1%1 [L]
# ignore trap for non-image requests, rewrite URL without trap segment
RewriteRule (.*)rwd-router/(.*)$ $1$2
这里我们需要注意到的是RewriteCond 和 RewriteRule,RewriteCond指令定义一条规则条件,只有当URL与自身的正则表达式匹配且符合RewriteRule规则时,才能被处理。
拿刚才的URL = "http://filamentgroup.com/examples/responsive-images/rwd-router/small.jpg?full=large.jpg"来说,只有当URL匹配 full=(.*)&?,且符合 (.*)rwd-router/.*\.(jpe?g|png|gif|webp) 时,才能应用于规则 $1%1。
1)$N:RewriteRule后向引用,其中(0 <= N <= 9) 。$N引用紧跟在RewriteCond后面的RewriteRule中模板中的括号中的模板在当前URL中匹配的数据。
2)%N:RewriteCond后向引用,其中(0 <= N <= 9) 。%N引用最后一个RewriteCond的模板中的括号中的模板在当前URL中匹配的数据。
$1%1 简单来说,就是将URL匹配RewriteRule后的结果集的第二项,替换成URL匹配RewriteCond结果集的第二项。URL匹配RewriteRule后的结果集的第二项为rwd-router/small.jpg?full=large.jpg
URL匹配RewriteCond后的结果集的第二项为large.jpg
替换之后的结果为http://filamentgroup.com/examples/responsive-images/large.jpg
到此,在页面图片显示出来之前,就将URL重定向到了large图片。所以当图片显示出来的时候,直接就是显示对应的大图或者小图。
如果浏览器不支持动态base标签(例如Firefox),则它的代码提供了另外一种方式,就是直接替换img标签中的src,代码如下。
for( var i = 0, imgs = doc.getElementsByTagName( "img" ), il = imgs.length; i < il; i++){
var img = imgs[i],
src = img.getAttribute( "src" ),
full = src.match( /(\?|&)full=(.*)&?/ ) && RegExp.$2;
if( full ){
img.src = full;
}
}
浏览器在src属性的内容改变时,会重新获取一次图片。
当dom渲染完毕之后,程序会删除掉之前添加的base标签(在支持base标签的情况下),让全局路径恢复原始的。
整个过程都在图片加载之前完成!