HTML5学堂-码匠 HTML5学堂

您当前位于:移动端基础 ——> 移动端开发知识[系列] - 固定像素的实现方法,使用px实现移动端

移动端开发知识[系列] - 固定像素的实现方法,使用px实现移动端

2015/07/04 20:00:58 | 作者:HTML5学堂(码匠) | 分类:移动端基础 | 关键词:移动端,固定像素,实现方法,MetaHandler

移动端H5知识[系列] - 固定像素的实现方法

HTML5学堂:随着对移动端的探索,而今我们逐渐形成了“横向百分比,纵向rem”。日前看网易对移动端的操作,发现网易的lofter采用了固定像素进行制作。今天我们就来剖析一下这种方法。

2015.08.19 测试手记:在魅族4当中的内置浏览器进行测试时,无论是我们书写的页面还是网易的lofter页面,都出现了bug问题,主要bug现象如下:当手指滑过部分文字的时候,文字的大小会出问题。经过排查之后,发现,在网页中的a标签会出现这个问题。当鼠标移动到a标签上的时候(即便不点击),标签的字体和行高会失效。具体原因以及解决办法尚不明确。

关于这种方法,其实在六月初的时候和我们的能堡讲师在使用lofter的时候,就已经看到了这种用法,但是一直没有放到实际的课程当中,其主要原因是没有进行实际操作。这次HTML5学堂的移动端官网,我们也采用了这种方法。

使用的基本框架

主要使用的基本框架是:MetaHandler.js。大家可以点击此处下载——“下载MetaHandler.js”,提取密码为:9074,也可以直接复制下面的代码。

  1. !function () {
  2.     var opt = function() {
  3.         var ua = navigator.userAgent,
  4.             android = ua.match(/(Android);?[\s\/]+([\d.]+)?/),
  5.             ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
  6.             ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/),
  7.             iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
  8.             os = {};
  9.  
  10.         if (android){ os.android = true, os.version = android[2];}
  11.         if (iphone && !ipod) {os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');}
  12.         if (ipad) {os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');}
  13.         if (ipod) {os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;}
  14.  
  15.         var MetaHandler = function(){
  16.             //MONOSTATE
  17.             if(MetaHandler.prototype.instance){
  18.                 return MetaHandler.prototype.instance;
  19.             }
  20.             var me = this;
  21.             var meta = {},_els;
  22.  
  23.             /**
  24.              * _els
  25.              * meta = {name:{content:String,seriation:Array,store:{property:String},...},...}
  26.              * @method init
  27.              */
  28.             function init(){
  29.                 _els = document.getElementsByTagName('meta');
  30.                 for(var i=0;i<_els.length;i++){
  31.                     var name = _els[i].name;
  32.                     if(name){
  33.                         meta[name] = {};
  34.                         meta[name].el = _els[i];
  35.                         meta[name].content = _els[i].content;
  36.                         meta[name].seriation = meta[name].content.split(',');
  37.                         meta[name].store = getContentStore(name);
  38.                     }
  39.                 }
  40.                 return me;
  41.             }
  42.             function getContentStore(name){
  43.                 var content = meta[name].seriation,store = {};
  44.                 for(var i=0;i<content.length;i++){
  45.                     if(content[i].length<1){
  46.                         content[i] = null;
  47.                         delete content[i];
  48.                         content.length--;
  49.                     }else{
  50.                         var ct = content[i].split('='),
  51.                             pp = ct[0];
  52.                         if(pp){
  53.                             store[pp] = ct[1];
  54.                         }
  55.                     }
  56.                 }
  57.                 return store;
  58.             }
  59.             this.hasMeta = function(name){
  60.                 return meta[name]?1:0;
  61.             }
  62.             this.createMeta = function(name){
  63.                 if(!this.hasMeta(name)){
  64.                     var el = document.createElement('meta');
  65.                     el.name = name;
  66.                     document.head.appendChild(el);
  67.                     meta[name] = {};
  68.                     meta[name].el = el;
  69.                     meta[name].content = '';
  70.                     meta[name].seriation = [];
  71.                     meta[name].store = {};
  72.                 }
  73.                 return me;
  74.             }
  75.             this.setContent = function(name,value){
  76.                 meta[name].content = value;
  77.                 meta[name].el.content = value;
  78.                 return me;
  79.             }
  80.             this.getContent = function(name){
  81.                 return meta[name] && meta[name].content;
  82.             }
  83.             function updateContent(name){
  84.                 meta[name].content = meta[name].seriation.join(',');
  85.                 me.setContent(name,meta[name].content);
  86.                 return me;
  87.             }
  88.             this.removeContentProperty = function(name,property){
  89.                 var _property = property;
  90.                 if(meta[name]){
  91.                     if(meta[name].store[_property]!=null){
  92.                         for(var i = 0;i<meta[name].seriation.length;i++){
  93.                             if(meta[name].seriation[i].indexOf(property+'=')!=-1){
  94.                                 meta[name].seriation[i] = null;
  95.                                 delete meta[name].seriation[i];
  96.                                 break;
  97.                             }
  98.                         }
  99.                     }
  100.                     updateContent(name);
  101.                 }
  102.                 return me;
  103.             }
  104.             this.getContentProperty = function(name,property){
  105.                 return meta[name] && meta[name].store[property];
  106.             }
  107.             this.setContentProperty = function(name,property,value){
  108.                 var _property = property,
  109.                     pv = property+'='+value;
  110.                 if(meta[name]){
  111.                     if(meta[name].store[_property]!=null){
  112.                         meta[name].store[_property] = value;
  113.                         for(var i = 0;i<meta[name].seriation.length;i++){
  114.                             if(meta[name].seriation[i].indexOf(property+'=')!=-1){
  115.                                 meta[name].seriation[i] = pv;
  116.                                 break;
  117.                             }
  118.                         }
  119.                     }else{
  120.                         meta[name].store[_property] = value;
  121.                         meta[name].seriation.push(pv);
  122.                     }
  123.                     updateContent(name);
  124.                 }
  125.                 return me;
  126.             }
  127.  
  128.             this.fixViewportWidth = function(width,fixBody){
  129.                 width = width || me.getContentProperty('viewport','width');
  130.                 if(width != 'device-width'){
  131.                     var iw = window.innerWidth || width,
  132.                         ow = window.outerWidth || iw,
  133.                         sw = window.screen.width || iw,
  134.                         saw = window.screen.availWidth || iw,
  135.                         ih = window.innerHeight || width,
  136.                         oh = window.outerHeight || ih,
  137.                         sh = window.screen.height || ih,
  138.                         sah = window.screen.availHeight || ih,
  139.                         w = Math.min(iw,ow,sw,saw,ih,oh,sh,sah),
  140.                         ratio = w/width,
  141.                         dpr = window.devicePixelRatio;
  142.                     ratio = Math.min(ratio,dpr);
  143.  
  144.                     //fixBody may trigger a reflow,you should not use it if you could do it in your css
  145.                     if(fixBody){
  146.                         document.body.style.width = width+'px';
  147.                     }
  148.  
  149.                     if(os.android){
  150.                         me.removeContentProperty('viewport','user-scalable')
  151.                             .setContentProperty('viewport','target-densitydpi','device-dpi')
  152.                             .setContentProperty('viewport','initial-scale',ratio)
  153.                             .setContentProperty('viewport','maximum-scale',ratio);
  154.                     }else if(os.ios && !os.android){
  155.                         me.setContentProperty('viewport','user-scalable','no');
  156.                         if(os.ios && parseInt(os.version)<7){
  157.                             me.setContentProperty('viewport','initial-scale',ratio);
  158.                         }
  159.                     }
  160.                 }
  161.             }
  162.             init();
  163.             //MONOSTATE
  164.             MetaHandler.prototype.instance = this;
  165.         };
  166.         return new MetaHandler;
  167.     }();
  168.  
  169.     // HTML5友情提示 —— 调用自适应屏幕的功能函数
  170.     opt.fixViewportWidth(1080);
  171. }();

基本原理

主要利用了视口中的缩放值,在视口设置当中,可以通过调整缩放值,控制网页的整体缩放。从而达到每个页面效果相同。应该说是一个不错的方法吧。

具体使用步骤

想实现这个功能,其实并不难,几个简单的步骤就能够搞定。我们一起来看一下:

1、按照PSD图的实际宽度,使用像素单位进行页面的基本书写(和写PC端页面一样啦)。在页面顶部添加meta,设置视口信息,将width设置为PSD图的实际宽度(即制作页面时的实际宽度)。但是不需要设置缩放值。demo如下:

  1. <meta content="target-densitydpi=device-dpi,width=1080" name="viewport">

2、修改MetaHandler.js文件的最后配置代码。在执行fixViewportWidth函数时,传入相应的像素值作为参数即可。

  1. // HTML5友情提示 —— 调用自适应屏幕的功能函数
  2. opt.fixViewportWidth(1080);

3、第三步?没有第三步了~!!!是不是很简单?

可能的问题

在使用谷歌浏览器进行浏览时,如果横屏后点击刷新,则页面会再缩小,成为居中显示状态,此时再竖屏之后,左右也会留白(此时再刷新是能重新恢复正常)。具体效果如下。

横屏后再刷新的效果:

横屏后再刷新的效果

从横屏恢复到纵屏的状态:

从横屏恢复到纵屏的状态

我们的看法:很少有人在旋转到横屏之后再刷新页面。而且目前移动端使用谷歌浏览器的人也很少,所以个人感觉这个bug是可以忽略的。另外,对于横屏转回到纵屏的时候,实际上我们是可以进行设备方向检测,然后再触发一次页面刷新,就不会出现纵屏上的问题了~

最后的话:我们使用了这个框架进行页面的开发,但是最近在使用时,感觉到在一些浏览器当中有些卡顿,用同样的设备和浏览器去测试了网易的手机页面,倒是没有什么卡顿现象,关于卡顿的问题,目前还在思考当中~~~

欢迎沟通交流~HTML5学堂

微信公众号,HTML5学堂,码匠,原创文章,WEB前端,技术分享

HTML5学堂

原创前端技术分享

HTML5学堂,HTML5,WEB,前端,视频课程,技术视频,学习视频,面试,JS

原创视频课程

用心打造精品课程

微信小程序,决胜前端,面试题,面试题集合,前端,HTML5,真题

小程序-决胜前端

前端面试题宝库

原创书籍,学习书籍,书籍推荐,HTML5布局之路,HTML5,WEB前端

HTML5布局之路

非传统模式讲解前端

iOS,APP,码集,案例交互,JavaScript学习,WEB前端,HTML5

iOS APP 码集

案例交互式学习JS