1. 程式人生 > >網頁的縮放,適配以及移動的適配!

網頁的縮放,適配以及移動的適配!

 

        從佈局出發:寬度自適應,常用百分比的方式。由於父級元素採用百分比的佈局方式,隨著螢幕的拉伸,它的寬度會無限的拉伸。而子元素由於採用了浮動,那麼它們的位置也會固定在兩端。該寬度自適應在新的時代有了新的方法,隨著彈性佈局的普及,它經常被flex或者box這樣的伸縮性佈局方式替代,

1.rem

        rem屬性指的是相對於根元素設定某個元素的字型大小。它同時也可以用作為設定高度等一系列可以用px來標註的單位。

       瀏覽器的預設字型高度一般為16px,即1em:16px,但是 1:16 的比例不方便計算,為了使單位em/rem更直觀,CSS編寫者常常將頁面跟節點字型設為62.5%,比如選擇用rem控制字型時,先需要設定根節點html的字型大小,因為瀏覽器預設字型大小16px*62.5%=10px。

html {
 font-size: 10px;
}

div {
 font-size: 1rem;
 height: 2rem;
 width: 3rem;
 border: .1rem solid #000;
}

    採用以上寫法,div繼承到了html節點的font-size,為本身定義了一系列樣式屬性,此時1em計算為10px,即根節點的font-size值。所以,這時div的高度就是20px,寬度是30px,邊框是1px,字型大小則是10px;一旦有了這樣的方法,我們自然可以根據不同的螢幕寬度設定不同的根節點字型大小。假設我們現在設計的標準是iphone5s,iphone5系列的螢幕解析度是640。為了統一規範,我們將iphone5 解析度下的根元素font-size設定為100px;

html {
 font-size: 100px;
}

/*
資料計算公式 640/100 = device-width / x  可以設定其他裝置根元素字型大小
ihone5: 640  : 100
iphone6: 750 : 117
iphone6s: 1240 : 194
*/
var deviceWidth = window.documentElement.clientWidth;
document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

        接下來我們可以根據根元素的字型大小用rem設定各種屬性的相對值。當然,如果是移動裝置,螢幕會有一個上下限制,我們可以控制解析度在某個範圍內,超過了該範圍,我們就不再增加根元素的字型大小了.

        一般的情況下,你是不需要考慮螢幕動態地拉伸和收縮。當然,假如使用者開啟了轉屏設定,在網頁載入之後改變了螢幕的寬度,那麼我們就要考慮這個問題了。解決此問題也很簡單,監聽螢幕的變化就可以做到動態切換元素樣式。

var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';


window.onresize = function(){
      var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
      document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';
 };

//為了提高效能,讓程式碼開起來更加完美,可以為它加上節流閥函式:
window.onresize = _.debounce(function() {
      var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
      document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';
}, 50);

 

2.css--media query(媒體查詢)

       運用css新屬性media query 特性也可以實現我們上說到過的佈局樣式。為尺寸設定根元素字型大小,但靈活性不高,取每個裝置的精確值需要自己去計算,所以只能取範圍值。考慮裝置螢幕眾多,解析度也參差不齊,把每一種機型的css程式碼寫出來是不太可能的。

    常用於pc端的適配,比如常見的1024,1366等解析度。此種自適應佈局一般常用在相容PC和手機裝置,由於螢幕跨度很大,介面的元素以及遠遠不是改改大小所能滿足的。這時候需要重新設計整介面的佈局和排版了,與rem相比,最明顯的特點是直接可以改變佈局。

      許多css框架經常用到這樣的多端解決方案,著名的bootstrap就是採用此種方式進行柵格佈局的。

@media screen and (device-width: 640px) { /*iphone4/iphon5*/
      html {
        font-size: 100px;
      }
    }

@media screen and (device-width: 750px) { /*iphone6*/
      html {
        font-size: 117.188px;
      }
    }
@media screen and (device-width: 1240px) { /*iphone6s*/
      html {
        font-size: 194.063px;
      }
    }

 

小結


1.如果只做pc端,那麼靜態佈局(定寬度)是最好的選擇;
2.如果做移動端,且設計對高度和元素間距要求不高,那麼彈性佈局(rem+js)是最好的選擇,一份css+一份js調節font-size搞定;
3.如果pc,移動要相容,而且要求很高那麼響應式佈局還是最好的選擇,前提是設計根據不同的高寬做不同的設計,響應式根據媒體查詢做不同的佈局。

 

 

場景1:1920的設計稿,需要在1024,1366等等主流解析度下適配(採用網頁等比例縮放)

常見的縮放有zoom和transform:scale兩種,兩者都具備縮放的功能,他們的區別如下

1.zoom支援的值型別有:

  1. 百分比值:zoom:50%,表示縮小到原來的一半。
  2. 數值:zoom:0.5,表示縮小到原來的一半。
  3. normal關鍵字:zoom:normal等同於zoom:1.

注意,雖然Chrome/Safari瀏覽器支援了zoom屬性,但是,其實zoom並不是標準屬性。

2、CSS3 transform下的scale

transform下的scale就不一樣了,是明明確確寫入規範的。從IE9+到其他現代瀏覽器都支援。語法為:transform: scale(<x> [<y>]). 同時有scaleXscaleY專門的xy方向的控制。

zoom不同,scale並不支援百分比值和normal關鍵字,只能是數值。而且,還能是負數,沒錯,負數。而zoom不能是負值!

3、zoom和scale更深層次的差異

  控制縮放的值不一樣。zoom更全面,但是不能是負數,只能等比例控制;而scale雖然只能是數值,但是能負數,可以只控制1個維度。

  1. zoom的縮放是相對於左上角的;而scale預設是居中縮放;
  2. zoom的縮放改變了元素佔據的空間大小;而scale的縮放佔據的原始尺寸不變,頁面佈局不會發生變化;
  3. zoom和scale對元素的渲染計算方法可能有差異(如下截圖示意)。
  4. 對文字的縮放規則不一致。zoom縮放依然受限於最小12畫素中文大小限制;而scale就是純粹的對圖形進行比例控制,文字50%原來尺寸。

    文字控制規則差異

然後,還有一個肉眼看不見卻更重要的差異,渲染的效能差異明顯

由於zoom的縮放會改變元素的真實空間大小,會影響其它的元素,在文件流中zoom加在任意一個元素上都會引起一整個頁面的重新渲染,而scale只是在當前的元素上重繪。即scale變化時其原本的尺寸是不變的,但zoom則會改變其原來尺寸。

我們要實現元素的縮放效果,可以使用CSS3 animation, 但是存在這樣一種情況,就是元素原本就使用了一些transform屬性進行,此時,再使用scale進行animation縮放,就會覆蓋原來的值,事情就會變得麻煩。

在移動端,大家也可以使用zoom進行一些靜態內容的控制,可以避免為了scale而佔有translaterotateskew等公用的transform屬性。

需要注意的是,Chrome等瀏覽器下,zoom/scale不要同時使用,因為,縮放效果會累加。

下面是不改變整體佈局時進行的筆記本適配。將網頁進行整體縮放。效果相當於ctrl+滑鼠滾動j進行網頁的縮放,只不過這是通過計算比例,然後在具體的解析度下顯示縮放後的網頁(無需手動縮放),業務場景應該是希望內容一屏顯示,在不同的解析度下不希望出現滾動條。

function zoomhtml(){
                var wid=$(window).width(),len;
                if(wid<1600){
                        len=wid/1600;
                        $("html").css("zoom",len);
                        $("html").css({"-moz-transform":"scale("+len+")"},{"-moz-transform-origin":"0 0"});
                }
        };
        zoomhtml();

 

場景2 :經常會遇到一些需求是頁面鋪滿整個螢幕,即:螢幕有多高頁面就有多高不能出現滾動條。

可用如下的方式解決

 1.設定頁面viewport初始縮放為1

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">


2.頁面結構如下;其中content為目標縮放容器

<body class="container">
    <div class="main_content content">
    </div>
</body>



3.js指令碼如下,需要放在頁面最底部

<script>
        var clientWidth = parent.document.documentElement.clientWidth;
        var clientHeight = parent.document.documentElement.clientHeight;

        resize(clientWidth, clientHeight);
        window.addEventListener('resize', resize(clientWidth, clientHeight));
        function resize(docWidth, docHeight) {
            var docScale = docHeight / docWidth,
                designWidth = 375, designHeight = 667, els = document.querySelectorAll('.content'),
                scale = docWidth / designWidth,
                scaleX = docWidth / designWidth,
                scaleY = docHeight / designHeight;
            convertArray(els).forEach(function (el) {
                extend(el.style, {
                    width: designWidth + 'px',
                    height: (docScale * designWidth) + 'px',
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    transformOrigin: '0 0',
                    webkitTransformOrigin: '0 0',
                    transform: 'scale(' + scale + ')',
                    webkitTransform: 'scale(' + scale + ')',
                    overflow: 'auto',
                    webkitOverflowScrolling: 'touch'
                });
            });
        }
        function convertArray(arrayLike) {
            return Array.prototype.slice.call(arrayLike, 0);
        }
    
        function extend() {
            var args = Array.prototype.slice.call(arguments, 0);
            return args.reduce(function (prev, now) {
                for (var key in now) {
                    if (now.hasOwnProperty && now.hasOwnProperty(key)) {
                        prev[key] = now[key];
                    }
                }
                return prev;
            });
        }
    </script>
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8" /> 
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no"> 
<title>測試頁面</title> 
<style type="text/css"> 
div { 
width: 600px; 
text-align: center; 
font-size: 4em; 
color: #333; 
} 
</style> 
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"></script> 
<script type="text/javascript"> 
$(function() { 
var r = document.body.offsetWidth / window.screen.availWidth; 
$(document.body).css("-webkit-transform","scale(" + r + ")"); 
}); 
$(window).resize(function() { 
var r = document.body.offsetWidth / window.screen.availWidth; 
$(document.body).css("-webkit-transform","scale(" + r + ")"); 
}); 
</script> 
</head> 
<body> 
<div>改變視窗大小試試,你會發現什麼?</div> 
</body> 
</html> 

最後:

   希望你看了文章有所收穫,歡迎交流!如有錯誤,歡迎指正!