Responsive-Images响应式图片插件的工作原理
一、什么是响应式图片
随着不同分辨率的移动设备出现,网页需要在不同分辨率的设备下给用户提供更加舒适的体验,随之就出现了响应式布局的概念。
响应式布局是Ethan Marcotte提出来的,说白了就是一个网站能兼容不同分辨率的设备,而无需为每一个分辨率的终端各写一个网页。
其主要用到的技术是CSS3中的Media Query以及为了兼容古董浏览器而生的各种插件。而响应式图片不同,它使用的是javascript和服务器的方式去实现。响应式图标不单单是简单的把IMG元素根据屏幕大小去缩放,而是在一定尺寸的设备中,使用不同分辨率(也就是图片大小)不同的图片。
二、响应式图片的好处
低分辨率的设备大部分都是移动设备,如果在分辨率较低时,让网页去加载对应分辨率较低的图片,不仅会加快网页的呈现速度,而且能节省流量。
三、Responsive-Images
Responsive-Images是一个响应式图片的解决方案,它将在屏幕分辨率小于480px的时候加载小尺寸的图片。源码可以在 Github上下载,也可以在这里看到 DEMO。
它主要是根据服务器重定向或IMG标签路径替换的方式来实现响应式图片,下面解释一下它的工作原理。
四、使用方法
1.网站所使用的服务器必须是apache
2.将“.htaccess”文件拷贝到apache web 服务器的根文件头中
3.在页面的<head>中导入“responsiveimgs.min.js”
4.<img src="small.jpg?full=large.jpg" >
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标签,并加入到<head>标签中,不知道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/"
这段代码执行过后,在<head>标签中生成了这样一个标签:
<base href="http://filamentgroup.com/examples/responsive-images/rwd-router/"></base>这是一个虚拟全局路径,点击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标签的情况下),让全局路径恢复原始的。
整个过程都在图片加载之前完成!