metahandler.js——移动端适配各种屏幕无痛工具脚本

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

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

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

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

使用的基本框架

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

!function () {
   var opt = function() {
       var ua = navigator.userAgent,
           android = ua.match(/(Android);?[\s\/]+([\d.]+)?/),
           ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
           ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/),
           iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
           os = {};


       if (android){ os.android = true, os.version = android[2];}
       if (iphone && !ipod) {os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');}
       if (ipad) {os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');}
       if (ipod) {os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;}


       var MetaHandler = function(){
           //MONOSTATE
           if(MetaHandler.prototype.instance){
               return MetaHandler.prototype.instance;
           }
           var me = this;
           var meta = {},_els;


           /**
            * _els
            * meta = {name:{content:String,seriation:Array,store:{property:String},...},...}
            * @method init
            */
           function init(){
               _els = document.getElementsByTagName('meta');
               for(var i=0;i<_els.length;i++){
                   var name = _els[i].name;
                   if(name){
                       meta[name] = {};
                       meta[name].el = _els[i];
                       meta[name].content = _els[i].content;
                       meta[name].seriation = meta[name].content.split(',');
                       meta[name].store = getContentStore(name);
                   }
               }
               return me;
           }
           function getContentStore(name){
               var content = meta[name].seriation,store = {};
               for(var i=0;i<content.length;i++){
                   if(content[i].length<1){
                       content[i] = null;
                       delete content[i];
                       content.length--;
                   }else{
                       var ct = content[i].split('='),
                           pp = ct[0];
                       if(pp){
                           store[pp] = ct[1];
                       }
                   }
               }
               return store;
           }
           this.hasMeta = function(name){
               return meta[name]?1:0;
           }
           this.createMeta = function(name){
               if(!this.hasMeta(name)){
                   var el = document.createElement('meta');
                   el.name = name;
                   document.head.appendChild(el);
                   meta[name] = {};
                   meta[name].el = el;
                   meta[name].content = '';
                   meta[name].seriation = [];
                   meta[name].store = {};
               }
               return me;
           }
           this.setContent = function(name,value){
               meta[name].content = value;
               meta[name].el.content = value;
               return me;
           }
           this.getContent = function(name){
               return meta[name] && meta[name].content;
           }
           function updateContent(name){
               meta[name].content = meta[name].seriation.join(',');
               me.setContent(name,meta[name].content);
               return me;
           }
           this.removeContentProperty = function(name,property){
               var _property = property;
               if(meta[name]){
                   if(meta[name].store[_property]!=null){
                       for(var i = 0;i<meta[name].seriation.length;i++){
                           if(meta[name].seriation[i].indexOf(property+'=')!=-1){
                               meta[name].seriation[i] = null;
                               delete meta[name].seriation[i];
                               break;
                           }
                       }
                   }
                   updateContent(name);
               }
               return me;
           }
           this.getContentProperty = function(name,property){
               return meta[name] && meta[name].store[property];
           }
           this.setContentProperty = function(name,property,value){
               var _property = property,
                   pv = property+'='+value;
               if(meta[name]){
                   if(meta[name].store[_property]!=null){
                       meta[name].store[_property] = value;
                       for(var i = 0;i<meta[name].seriation.length;i++){
                           if(meta[name].seriation[i].indexOf(property+'=')!=-1){
                               meta[name].seriation[i] = pv;
                               break;
                           }
                       }
                   }else{
                       meta[name].store[_property] = value;
                       meta[name].seriation.push(pv);
                   }
                   updateContent(name);
               }
               return me;
           }


           this.fixViewportWidth = function(width,fixBody){
               width = width || me.getContentProperty('viewport','width');
               if(width != 'device-width'){
                   var iw = window.innerWidth || width,
                       ow = window.outerWidth || iw,
                       sw = window.screen.width || iw,
                       saw = window.screen.availWidth || iw,
                       ih = window.innerHeight || width,
                       oh = window.outerHeight || ih,
                       sh = window.screen.height || ih,
                       sah = window.screen.availHeight || ih,
                       w = Math.min(iw,ow,sw,saw,ih,oh,sh,sah),
                       ratio = w/width,
                       dpr = window.devicePixelRatio;
                   ratio = Math.min(ratio,dpr);


                   //fixBody may trigger a reflow,you should not use it if you could do it in your css
                   if(fixBody){
                       document.body.style.width = width+'px';
                   }


                   if(os.android){
                       me.removeContentProperty('viewport','user-scalable')
                           .setContentProperty('viewport','target-densitydpi','device-dpi')
                           .setContentProperty('viewport','initial-scale',ratio)
                           .setContentProperty('viewport','maximum-scale',ratio);
                   }else if(os.ios && !os.android){
                       me.setContentProperty('viewport','user-scalable','no');
                       if(os.ios && parseInt(os.version)<7){
                           me.setContentProperty('viewport','initial-scale',ratio);
                       }
                   }
               }
           }
           init();
           //MONOSTATE
           MetaHandler.prototype.instance = this;
       };
       return new MetaHandler;
   }();


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

基本原理

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

具体使用步骤

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

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

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

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

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

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

可能的问题

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

横屏后再刷新的效果:

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

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

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

欢迎沟通交流~HTML5学堂

原文发布于微信公众号 - HTML5学堂(h5course-com)

原文发表时间:2015-08-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和我大前端的故事

2018 我所了解的 Vue 知识大全(一)

Vue ,React ,Angular 三大主流框架,最后我选择学习 Vue ,接触过 React ,自己感觉学习曲线有些陡峭,进而我选择了学习 Vue ,他的...

893
来自专栏菩提树下的杨过

js小技巧:延时加载Flash

当页面中包含自动播放视频的flash播放器时,flash的流媒体播放会一直不停的下载视频(哪怕你点击了播放暂停/停止也一样在不停下载),这样会影响到页面其它元素...

31410
来自专栏速成应用小程序开发平台

新手教程--手把手教你从零开始制作一款电商必备的商城小程序

近年来,在电商、新零售趋势的影响下,实体零售商也都在谋求自身的渠道变革,完善消费体验。如今微信已有超过十亿的用户,市场巨大,而微信小程序的开通不仅能够降低品牌...

1422
来自专栏葡萄城控件技术团队

Angular和Vue.js 深度对比

Vue.js 是开源的 JavaScript 框架,能够帮助开发者构建出美观的 Web 界面。当和其它网络工具配合使用时,Vue.js 的优秀功能会得到大大加强...

5443
来自专栏逸鹏说道

无图片字体icon

W3C 仍然在对 CSS3 规范进行开发。不过,现代浏览器已经实现了相当多的 CSS3 属性。CSS3也从前几年的初试探到如今的广泛应用。最近折腾这方面的东西其...

3619
来自专栏思衍 Jax 专栏

企鹅辅导课程详情页毫秒开的秘密 - PWA 直出

随着近几年的前端技术的高速发展,越来越多的团队使用 React、Vue 等 SPA 框架作为其主要的技术栈。以 React 应用为例,从性能角度,其最重要的指标...

88011
来自专栏Youngxj

杨小杰站长之家工具箱1.1

1725
来自专栏企鹅号快讯

做网站-如何将设计稿还原为网页

做网站开发的伙伴应该很清楚,一个网站从设计到开发完成,经过的步骤,除了需求功能这些不说以外,其余的就是展现给用户的视觉上的效果了。一般由美工或者说设计师设计出页...

25110
来自专栏游戏杂谈

IOS设计指南

以前整理过一份关于关于《IOS应用提交时所需要的ICON》,之后IPhone 6/Plus出来,又多了二种尺寸,近期看到国外的一家网站上整理出比较全的尺寸,以及...

931
来自专栏王大锤

iOS各种调试技巧豪华套餐

4029

扫码关注云+社区