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标签的情况下),让全局路径恢复原始的。

整个过程都在图片加载之前完成!





 


你可能感兴趣的:(JavaScript,正则表达式,浏览器,响应式,移动设备)