专业 靠谱 的软件外包伙伴

您的位置:首页 > 新闻动态 > HTML5-移动端软件开发响应式布局新方案

HTML5-移动端软件开发响应式布局新方案

2016-08-24 14:27:54

前言

  大家都知道当下,手机屏幕大小多种多样,而且即使同样大小的size,每个手机的设备像素比还不一样。当我们选用html5来开发移动应用的时候,有没有一种合适的方案来完美的适配到所有的屏幕呢? 
对移动端接触不多的,可以先了解下移动端的单位、viewport的概念。这里也不再赘述,通过以下连接了解。 
1.http://www.cnblogs.com/2050/p/3877280.html  2.http://tgideas.qq.com/webplat/info/news_version3/804/7104/7106/m5723/201509/376281.shtml

经典方式

  先简要的介绍下现在多数开发者使用的方式,由于这些方式大家或多或少都使用过,而且网上也有非常详细的教程,我就不再重复造轮子,只是简单的列举下。 
1.css3 @media

http://www.w3cways.com/1180.html 
这种方式适配起来良好,但是还是无法兼容所有的屏幕,而且各个样式都用@media写几套,很麻烦,也不利于后期扩展维护。

2.px+百分百+flex

像目前接触过的一些前端框架ionic、bootstrap、amaze、mui等,对于已经确定无需随屏幕变化的元素,一般用px固定大小,对于宽度的处理用百分比或flex来灵活处理。

这种方式处理起来,大体还好,但是对于小屏iphone5s和大屏iphone6 plus,某些布局只能折中处理。最大的缺陷是, 一些布局无法通过百分比或者flex设置的时候,布局的样式和字体的大小都无法随屏幕的变化而响应式变化。

3.对于viewport的处理

  • 固定高度,宽度自适应
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
  • 		1
  • 固定宽度,动态生成viewport
var fixScreen = function() {
    var metaEl = doc.querySelector('meta[name="viewport"]'),
        metaCtt = metaEl ? metaEl.content : '',
        matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/),
        matchWidth = metaCtt.match(/width=([^,\s]+)/);
    if ( metaEl && !matchScale && ( matchWidth && matchWidth[1] != 'device-width') ) {
        var width = parseInt(matchWidth[1]),
            iw = win.innerWidth || width,
            ow = win.outerWidth || iw,
            sw = win.screen.width || iw,
            saw = win.screen.availWidth || iw,
            ih = win.innerHeight || width,
            oh = win.outerHeight || ih,
            ish = win.screen.height || ih,
            sah = win.screen.availHeight || ih,
            w = Math.min(iw,ow,sw,saw,ih,oh,ish,sah),
            scale = w / width;
        if ( ratio < 1) {
            metaEl.content += ',initial-scale=' + ratio + ',maximum-scale=' + ratio + ', minimum-scale=' + scale;
        }
    }
}
  • 		1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

详细处理方式请看以下链接,  https://github.com/riskers/blog/issues/18  http://html-js.com/article/MobileWeb

4.根节点固定fontSize,布局单位用rem  动态生成根节点的fontSize:

<script type="text/javascript">
    /*
     * 如果页面的宽度超过了640px,那么页面中 html
     * 的font-size恒为100px,否则,页面中html的
     * font-size的大小为: 100 * (当前页面宽度 / 640)
     *字体大小或者其他div宽高度 * html的font=该元素的实际大小px (htmlFont*(fontRem || divRem)=realPx)
     */
        (function(doc,win){
            var docEle=doc.documentElement;
            var resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize';
            var recalc = function(){
                var clientWidth = docEle.clientWidth;
                if(!clientWidth)
                    return;
                if(clientWidth>=640){
                    docEle.style.fontSize='100px';
                }else{
                    docEle.style.fontSize=100*(clientWidth/640) + 'px';
                }
            };
            if(!doc.addEventListener)
                return;
            win.addEventListener(resizeEvt,recalc,false);
            doc.addEventListener('DOMContentLoaded',recalc,false);
        })(document,window);
    </script>
  • 		1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

页面上字体和布局单位都采用rem,该方式基本可以适应大部分的布局,使用过程中发现一个缺陷,由于,fontSize是根据屏幕的宽度自动生成的,那么在横屏的时候,由于设置的元素的高度rem是基于宽度计算的fontSize来的,fontSize会变大,就会造成元素的高度被拉的很高。我们希望是这样的:布局元素的宽度始终基于屏幕宽度百分比变化,布局元素的高度始终基于屏幕高度百分比变化。有没有方法实现呢?答案是有,看下面的一种方式。

5.css3百分比单位vw,vh  1vw等于可视区宽度(屏幕的可视区域即布局区域)的百分之一,1vh等于可视区高度的百分之一

<div style="width:20vw;height:40vh;"></div>
  • 		1

表示当前元素在任何屏幕下都是div占当前屏幕宽度的20%,当前高度的40%。刚好满足我们的需求,但是你会发现很少有有开发者采用这个单位。很不幸,这个单位有部分浏览器和手机并不支持。我们有没有替代的解决方案呢?就是下面今天打算重点讲的一个方案。

angularjs指令计算百分方式

由于vw,vh不被完全支持的原因,有了这个替代的解决方案,目前项目中正在使用,效果很不错。  先上代码:

angular.module('starter.directives', [])
.directive('adaptive',function(){
    function link($scope, element, attrs) { 
        var dom=element[0]; 
        var wPercent = attrs.adaptiveW;
        var hPercent = attrs.adaptiveH;
        var pPercent = attrs.adaptiveP ? attrs.adaptiveP.split(",") : null;
        var mPercent = attrs.adaptiveM ? attrs.adaptiveM.split(",") : null;
        setWAndH();
        function setWAndH(){ 
            var screenW = Math.min(document.documentElement.clientWidth,window.innerWidth);
            var screenH = Math.min(document.documentElement.clientHeight,window.innerHeight);  
            if(wPercent){ //宽度
                dom.style.width=wPercent*screenW+"px";
            }
            if(hPercent){  //高度
                dom.style.height=hPercent*screenH+"px";
            }
            if(pPercent){//padding
                dom.style.paddingTop=pPercent[0]*screenH+"px";
                dom.style.paddingRight=pPercent[1]*screenW+"px";
                dom.style.paddingBottom=pPercent[2]*screenH+"px";
                dom.style.paddingLeft=pPercent[3]*screenW+"px";
            }
            if(mPercent){//margin
                dom.style.marginTop=mPercent[0]*screenH+"px";
                dom.style.marginRight=mPercent[1]*screenW+"px";
                dom.style.marginBottom=mPercent[2]*screenH+"px";
                dom.style.marginLeft=mPercent[3]*screenW+"px";
            }
        } 
        window.onresize=function(){
            setWAndH();
        };
    } 
    return {
        restrict: 'A',
        link: link 
    };
});
  • 		1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

使用:

<div adaptive data-adaptive-w='0.1' data-adaptive-h='0.1' style="border:solid 1px red;" data-adaptive-p="0.01,0,0,0" data-adaptive-m="0,0.08,0,0">
    动态计算百分比,div始终占屏幕宽度的百分之10,高度始终占屏幕的百分之10
</div>
  • 		1
  • 2
  • 3

  代码很简单,就不做过多解释。用html5的data属性添加我们自己的数据,通过指令封装。在指令里面拿到对应的属性的值,乘屏幕的宽高度,算出实际值,再设置到元素上面。实际上就是一个变相的vw、vh的实现。然后有一个监听屏幕大小变化的函数,比如切屏时候,元素的位置和大小也会随着变化。大家也可以在此基础上进行扩展以满足自己的需要,比如data-adaptive-m=”0,0.1,10px,20px”,然后在指令里面判断下是否包含px,这样扩展就可以用这种方式同时设置px间隔或百分比间隔。这种方式非常灵活,不影响你使用其他的方案,你可以对某一个、某几个有特殊需求的元素进行处理都可以。    有什么好的建议或其他方案欢迎留言讨论。说一点自己项目中使用的建议:确定要用固定px大小的,尽量用定值px,比如标题栏高度等;宽度布局时候尽量使用百分比或flex或者用指令实现的这种方式;高度需要自适应时候用指令这种方式非常方便;在处理字体大小的时候,如果产品没有特殊要求,可不对字做响应式处理,有特殊要求可以采用上面的rem的方式。

关于:中科研拓
深圳市中科研拓科技有限公司专注提供软件外包、app开发、智能硬件开发、O2O电商平台、手机应用程序、大数据系统、物联网项目等开发外包服务,十年研发经验,上百成功案例,中科院软件外包合作企业。通过IT技术实现创造客户和社会的价值,致力于为用户提供很好的软件解决方案。联系电话400-0316-532,邮箱sales@zhongkerd.com,网址www.zhongkerd.com


  上一篇   [返回首页] [打印] [返回上页]   下一篇