整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          可視化大屏的幾種屏幕適配方案,總有一種是你需要的

          可視化大屏的幾種屏幕適配方案,總有一種是你需要的

          設(shè)我們正在開發(fā)一個可視化拖拽的搭建平臺,可以拖拽生成工作臺或可視化大屏,或者直接就是開發(fā)一個大屏,首先必須要考慮的一個問題就是頁面如何適應(yīng)屏幕,因為我們在搭建或開發(fā)時一般都會基于一個固定的寬高,但是實際的屏幕可能大小不一,接下來我們就嘗試幾種簡單且常見的方案,并簡單分析一下利弊。

          demo

          首先寫個基礎(chǔ)的demo給后續(xù)使用:

          <script setup>
          import { ref } from "vue";
          import Widget from "./components/Widget.vue";
          import LineChart from "./components/LineChart.vue";
          import BarChart from "./components/BarChart.vue";
          import PieChart from "./components/PieChart.vue";
          import FunnelChart from "./components/FunnelChart.vue";
          
          // 畫布寬高
          const canvasWidth=ref(1920);
          const canvasHeight=ref(1080);
          // 組件寬高
          const widgetWidth=ref(960);
          const widgetHeight=ref(540);
          </script>
          
          <template>
            <div class="canvasBox">
              <div
                class="canvas"
                :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
              >
                <Widget :width="widgetWidth" :height="widgetHeight" :left="0" :top="0">
                  <LineChart></LineChart>
                </Widget>
                <Widget :width="widgetWidth" :height="widgetHeight" :left="widgetWidth" :top="0">
                  <BarChart></BarChart>
                </Widget>
                <Widget :width="widgetWidth" :height="widgetHeight" :left="0" :top="widgetHeight">
                  <PieChart></PieChart>
                </Widget>
                <Widget :width="widgetWidth" :height="widgetHeight" :left="widgetWidth" :top="widgetHeight">
                  <FunnelChart></FunnelChart>
                </Widget>
              </div>
            </div>
          </template>
          
          <style scoped>
          .canvasBox {
            width: 100vw;
            height: 100vh;
          }
          .canvas {
            position: relative;
          }
          </style>

          每個圖表組件的寬高都設(shè)為100%,然后都被Widget組件包裹,所以實際寬高是依賴Widget組件的,Widget組件為絕對定位,并且寬高、位置通過props傳入,模擬我們的拖拽操作,簡單起見,所有圖表的寬高我們都設(shè)為了相同的。

          Widget組件:

          <script setup>
          const props=defineProps({
            width: {
              type: Number,
              default: 0,
            },
            height: {
              type: Number,
              default: 0,
            },
            left: {
              type: Number,
              default: 0,
            },
            top: {
              type: Number,
              default: 0,
            },
          });
          </script>
          
          <template>
            <div
              class="widgetBox"
              :style="{
                width: width + 'px',
                height: height + 'px',
                left: left + 'px',
                top: top + 'px',
              }"
            >
              <slot></slot>
            </div>
          </template>
          
          <style scoped>
          .widgetBox {
            position: absolute;
          }
          </style>

          組件整體的容器為類名為canvas的元素,相對定位,寬高也是動態(tài)設(shè)置的,canvas元素的父級canvasBox元素寬高設(shè)為和屏幕寬高一致。

          固定尺寸

          即寬度、高度固定,如果寬高小于屏幕寬高則在屏幕居中。

          這個是最簡單的方案了,相當(dāng)于不適配屏幕,畫布配置了多大實際就是多大,不隨屏幕的變化而變化,所以各個組件的寬高也是在配置后不會改變,一般用于尺寸固定且后期不會改變的可視化大屏。

          我們前面的demo初始就是這種方式:

          當(dāng)然,如果寬高小于屏幕的話居中的邏輯需要加一下,居中的方法有很多,通過css、js都可,根據(jù)自己的喜好來就行:

          // 畫布的位置
          const canvasLeft=ref(0);
          const canvasTop=ref(0);
          // 如果屏幕的寬或高比畫布的大,那么居中顯示
          let windowWidth=window.innerWidth;
          let windowHeight=window.innerHeight;
          if (windowWidth > canvasWidth.value) {
              canvasLeft.value=(windowWidth - canvasWidth.value) / 2;
          }
          if (windowHeight > canvasHeight.value) {
              canvasTop.value=(windowHeight - canvasHeight.value) / 2;
          }
          <div
                class="canvas"
                :style="{
                  width: canvasWidth + 'px',
                  height: canvasHeight + 'px',
                  left: canvasLeft + 'px',
                  top: canvasTop + 'px',
                }"
              >
          </div>

          判斷窗口寬度和高度是否大于畫布的寬高,是的話通過left或top來調(diào)整:

          自適應(yīng)寬度

          即寬度適應(yīng)屏幕,高度不變,這種方案的缺點是垂直方向上會出現(xiàn)滾動條。

          比如畫布設(shè)置的寬度為1920,但是實際上屏幕的寬度為1280,那么縮小了1.5倍,那么畫布和每個組件的寬度也需要同步縮小1.5倍,并且每個組件的left值也需要進行動態(tài)調(diào)整。

          首先實現(xiàn)一下容器元素canvas的尺寸調(diào)整:

          // 保存原始畫布的寬度
          const originCanvasWidth=ref(canvasWidth.value);
          // 寬度縮放比例
          const ratioWidth=ref(1);
          
          // 當(dāng)前窗口的寬度
          let windowWidth=window.innerWidth;
          // 將畫布寬度設(shè)置為當(dāng)前窗口的寬度
          canvasWidth.value=windowWidth;
          // 計算當(dāng)前寬度和原始寬度的比例
          ratioWidth.value=windowWidth / originCanvasWidth.value;

          然后再把這個比例傳給Widget組件進行調(diào)整:

          <Widget :ratioWidth="ratioWidth">
              <LineChart></LineChart>
          </Widget>
          <Widget :ratioWidth="ratioWidth">
              <BarChart></BarChart>
          </Widget>
          <Widget :ratioWidth="ratioWidth">
              <PieChart></PieChart>
          </Widget>
          <Widget :ratioWidth="ratioWidth">
              <FunnelChart></FunnelChart>
          </Widget>

          在Widget組件里我們只要把寬度和left都乘以這個比例即可,為什么是乘,很簡單:

          newWidth / width=ratioWidth=windowWidth / originCanvasWidth
          newWidth=width * ratioWidth
          
          // left同樣看做是一個距左側(cè)的寬度即可
          <div
              class="widgetBox"
              :style="{
                width: width * ratioWidth + 'px',
                height: height + 'px',
                left: left * ratioWidth + 'px',
                top: top + 'px',
              }"
            >
              <slot></slot>
          </div>

          自適應(yīng)屏幕

          即寬高都自適應(yīng),和上一種方案相比,這種橫豎都不會出現(xiàn)滾動條,且能完全鋪滿屏幕。

          實現(xiàn)也很簡單,在上一個【自適應(yīng)寬度】的基礎(chǔ)上加上高度自適應(yīng)即可。

          // 畫布原始寬高
          const originCanvasWidth=ref(canvasWidth.value);
          const originCanvasHeight=ref(canvasHeight.value);
          // 縮放比例
          const ratioWidth=ref(1);
          const ratioHeight=ref(1);
          
          // 當(dāng)前窗口的寬高
          let windowWidth=window.innerWidth;
          let windowHeight=window.innerHeight;
          // 將畫布寬高設(shè)置為當(dāng)前窗口的寬高
          canvasWidth.value=windowWidth;
          canvasHeight.value=windowHeight;
          // 計算當(dāng)前寬高和原始寬高的比例
          ratioWidth.value=windowWidth / originCanvasWidth.value;
          ratioHeight.value=windowHeight / originCanvasHeight.value;

          同樣再把比例傳給Widget組件進行調(diào)整:

          <Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight">
              <LineChart></LineChart>
          </Widget>
          <Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight">
              <BarChart></BarChart>
          </Widget>
          <Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight">
              <PieChart></PieChart>
          </Widget>
          <Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight">
              <FunnelChart></FunnelChart>
          </Widget>
          <div
              class="widgetBox"
              :style="{
                width: width * ratioWidth + 'px',
                height: height * ratioHeight + 'px',
                left: left * ratioWidth + 'px',
                top: top * ratioHeight + 'px',
              }"
            >
              <slot></slot>
          </div>

          整體等比例縮放

          即通過css的transform屬性來對組件容器canvas進行整體的縮放,保持原比例,在屏幕居中顯示,當(dāng)然你可以選擇只縮放寬度或高度,但是這樣會變形。

          前面的兩種方案,我們的組件開發(fā)時都必須要考慮容器的寬高,即需要進行適配,但是寬高比太極限了說實話很難處理,顯示效果肯定是比較差的,但是這種整體等比例適配就無需考慮這種情況。

          實際項目中如果有大屏需要適應(yīng)屏幕,我一般都通過這種方法,優(yōu)點是簡單,缺點是水平或垂直空間上可能會留白,但是背景是全屏的,所以效果也不會很差。

          實現(xiàn)也很簡單,計算一下畫布原始比例,再計算一下屏幕的比例,然后再判斷是寬度和屏幕一致,高度自適應(yīng),還是高度和屏幕一致,寬度自適應(yīng):

          // 當(dāng)前窗口寬高比例
          let windowWidth=window.innerWidth;
          let windowHeight=window.innerHeight;
          let windowRatio=windowWidth / windowHeight;
          // 畫布原始寬高比例
          const canvasRatio=canvasWidth.value / canvasHeight.value;
          // 計算畫布適應(yīng)后的新寬高
          let newCanvasWidth=0;
          let newCanvasHeight=0;
          if (canvasRatio > windowRatio) {// 畫布的寬高比大于屏幕的寬高比
              // 畫布的寬度調(diào)整為屏幕的寬度
              newCanvasWidth=windowWidth;
              // 畫布的高度根據(jù)畫布原比例進行縮放
              newCanvasHeight=windowWidth / canvasRatio;
          } else {// 畫布的寬高比小于屏幕的寬高比
              // 畫布的高度調(diào)整為屏幕的高度
              newCanvasHeight=windowHeight;
              // 畫布的寬度根據(jù)畫布原比例進行縮放
              newCanvasWidth=windowHeight * canvasRatio;
          }
          // ...

          假設(shè)屏幕的寬高相同,那么比例為1。

          第一種情況,假設(shè)畫布的寬是高的兩倍,那么比例為2,要保持原比例2適應(yīng)屏幕,顯然只能寬度和屏幕一致,高度自適應(yīng),因為如果高度和屏幕一致,那么寬度需要是高度的兩倍,屏幕顯然顯示不下:

          第二種情況,假設(shè)畫布的高是寬的兩倍,那么比例為0.5,要保持比例為0.5適應(yīng)屏幕,需要高度和屏幕一致,寬度自適應(yīng):

          計算完了畫布適應(yīng)屏幕后的新寬高,接下來就可以計算它相對于畫布原始寬高的縮放比例:

          // ...
          // 相對于畫布原始寬高的縮放比例
          const canvasStyle=reactive({
              transform: "",
          });
          const scaleX=newCanvasWidth / canvasWidth.value;
          const scaleY=newCanvasHeight / canvasHeight.value;
          canvasStyle.transform=`scale(${scaleX}, ${scaleY})`

          把樣式添加到容器元素canvas上即可:

          <div
                class="canvas"
                :style="{
                  width: canvasWidth + 'px',
                  height: canvasHeight + 'px',
                  ...canvasStyle
                }"
              >
          </div>

          顯示的位置似乎有點問題,這其實是因為默認情況下元素的變換都是以自身的中心點為原點進行變換的:

          我們只要改成以左上角為原點即可:

          const canvasStyle=reactive({
            transform: "",
            transformOrigin: `left top`// 改成以左上角為變換原點
          });

          最后再來讓它居中:

          // 居中
          const translateX=(windowWidth - newCanvasWidth) / 2 / scaleX;
          const translateY=(windowHeight - newCanvasHeight) / 2 / scaleY;
          canvasStyle.transform=`scale(${scaleX}, ${scaleY}) translate(${translateX}px, ${translateY}px)`;

          窗口的寬高減去畫布適應(yīng)后的新寬高,即剩余的空間,再除以2進行居中顯示,為什么還要除以縮放值呢,因為translate的值也會隨scale進行縮放,比如translateX計算出來為100,scaleX為0.5,那么實際上最終的偏移量為100*0.5=50,這顯然不對,所以我們除一個縮放值進行抵消。

          這個方案似乎很完美,那么還有沒有問題呢,顯然是有的,一個小問題是縮放后文字可能會模糊,這個問題不大,筆者遇到的另一個問題是如果使用了getBoundingClientRect方法獲取元素信息,本意是獲取元素原始的尺寸數(shù)據(jù),但是縮放后返回的就是縮放后的數(shù)據(jù),那么可能會和我們的原始意圖出現(xiàn)偏差,比如有一個如下的div:

          <div ref="el1" style="width: 200px; height: 200px; background: red; position: absolute; left: 50px; top: 50px;"></div>

          我們想要動態(tài)根據(jù)這個div大小和位置復(fù)制一個div:

          <div ref="el2" style="background: green; position: absolute"></div>
          const { width, height }=el1.value.getBoundingClientRect();
          const { left, top }=window.getComputedStyle(el1.value);
          el2.value.style.width=`${width}px`;
          el2.value.style.height=`${height}px`;
          el2.value.style.left=left;
          el2.value.style.top=top;

          可以看到獲取到的寬高比實際的小了一點,這顯然不是我們需要的,解決方法是要么不要使用getBoundingClientRect方法,使用offsetWdith等不會被縮放影響的方法或?qū)傩垣@取元素尺寸,要么把獲取到的數(shù)據(jù)除以縮放值。

          當(dāng)然可能還會存在其他一些屬性或方法也會存在這個問題,這就需要各位在實際的開發(fā)時進行測試了。

          總結(jié)

          本文簡單總結(jié)了一下大屏適配的幾種方法,沒有哪一種是最好的,也沒有哪一種是非常完美的,沒辦法,很多時候都是需要進行一定妥協(xié)的。

          demo地址:https://wanglin2.github.io/visual-drag-platform-fit-demo/

          demo倉庫地址:https://github.com/wanglin2/visual-drag-platform-fit-demo

          信很多自學(xué)的小伙伴都想學(xué)習(xí)web前端,可以關(guān)注小編后私信【學(xué)習(xí)】可以免費領(lǐng)取學(xué)習(xí)地址/案例教程/2018最新的一套學(xué)習(xí)教程,讓學(xué)習(xí)有方向。

          1、三角形列表項目符號

          ul {
           margin: 0.75em 0;
           padding: 0 1em;
           list-style: none;
          }
          li:before { 
           content: "";
           border-color: transparent #111;
           border-style: solid;
           border-width: 0.35em 0 0.35em 0.45em;
           display: block;
           height: 0;
           width: 0;
           left: -1em;
           top: 0.9em;
           position: relative;
          }
          

          2、外部CSS3 盒陰影

          #mydiv { 
           -webkit-box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.52);
           -moz-box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.52);
           box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.52);
          }
          

          3、內(nèi)部CSS3 盒陰影

          #mydiv { 
           -moz-box-shadow: inset 2px 0 4px #000;
           -webkit-box-shadow: inset 2px 0 4px #000;
           box-shadow: inset 2px 0 4px #000;
          }
          

          4、CSS3 斑馬線

          tbody tr:nth-child(odd) {
           background-color: #ccc;
          }
          

          5、強制出現(xiàn)垂直滾動條

          html { height: 101% }
          

          6、內(nèi)容垂直居中

          .container {
           min-height: 6.5em;
           display: table-cell;
           vertical-align: middle;
          } 
          

          7、CSS3:全屏背景

          html { 
           background: url('images/bg.jpg') no-repeat center center fixed; 
           -webkit-background-size: cover;
           -moz-background-size: cover;
           -o-background-size: cover;
           background-size: cover;
          }
          

          8、錨鏈接偽類

          a:link { color: blue; }
          a:visited { color: purple; }
          a:hover { color: red; }
          a:active { color: yellow; }
          

          9、為logo隱藏H1

          h1 {
           text-indent: -9999px;
           margin: 0 auto;
           width: 320px;
           height: 85px;
           background: transparent url("images/logo.png") no-repeat scroll;
          }
          

          10、自定義文本選擇

          ::selection { background: #e2eae2; }
          ::-moz-selection { background: #e2eae2; }
          ::-webkit-selection { background: #e2eae2; }
          

          11、跨瀏覽器的透明

          .transparent {
           filter: alpha(opacity=50); /* internet explorer */
           -khtml-opacity: 0.5; /* khtml, old safari */
           -moz-opacity: 0.5; /* mozilla, netscape */
           opacity: 0.5; /* fx, safari, opera */
          }
          

          12、新版清除浮動(2011)

          .clearfix:before, .container:after { content: ""; display: table; }
          .clearfix:after { clear: both; }
          /* IE 6/7 */
          .clearfix { zoom: 1; }
          

          13、典型的CSS清除浮動

          .clearfix:after {
           content: "."; 
           display: block;
           clear: both;
           visibility: hidden;
           line-height: 0;
           height: 0; 
          }
          .clearfix { display: inline-block; }
          html[xmlns] .clearfix { display: block; }
          * html .clearfix { height: 1%; }
          

          14、制造模糊文本

          想要讓文本模糊?可以使用color透明和text-shadow實現(xiàn)

          .blurry-text {
           color: transparent;
           text-shadow: 0 0 5px rgba(0,0,0,0.5);
          }
          

          15、CSS:表格列寬自適用

          對于表格,當(dāng)談到調(diào)整列寬時,是比較痛苦的。然后,這里有一個可以使用的技巧:給td元素添加white-space: nowrap;能讓文本正確的換行

          td {
           white-space: nowrap;
          }
          

          對前端有興趣或者正在學(xué)習(xí)web前端的小伙伴,可以私信小編【學(xué)習(xí)】即可免費領(lǐng)取2018最新的一整套系統(tǒng)web前端學(xué)習(xí)教程!

          端開發(fā)過程中,尺寸單位是我們必須用到的,下面我們對css中常見的幾種尺寸單位px,em,rem,rpx進行逐一介紹

          在這之前,需要先對幾個概念進行普及介紹

          基本概念

          (以下概念讀起來可能有些晦澀,如果看不懂也沒關(guān)系)

          像素

          它不是自然界的物理長度,指基本原色素及其灰度的基本編碼。

          css中的像素只是一個抽象的單位,在不同的設(shè)備或不同的環(huán)境中,css中的1px所代表的設(shè)備物理像素是不同的。

          在為桌面瀏覽器設(shè)計的網(wǎng)頁中,我們無需對這個津津計較,但在移動設(shè)備上,必須弄明白這點。

          在早先的移動設(shè)備中,屏幕像素密度都比較低,如iphone3,它的分辨率為320x480,在iphone3上,一個css像素確實是等于一個屏幕物理像素的。

          后來隨著技術(shù)的發(fā)展,移動設(shè)備的屏幕像素密度越來越高,從iphone4開始,蘋果公司便推出了所謂的Retina屏,分辨率提高了一倍,變成640x960,但屏幕尺寸卻沒變化,這就意味著同樣大小的屏幕上,像素卻多了一倍,這時,一個css像素是等于兩個物理像素的。其他品牌的移動設(shè)備也是這個道理。

          物理像素

          它是顯示器(電腦、手機屏幕)最小的物理顯示單位,物理像素指的是顯示器上最小的點。物理像素的大小取決于屏幕。是一個無法改變的屬性。

          設(shè)備獨立像素

          我上一張圖,你就會理解什么是設(shè)備獨立像素

          就是我們開發(fā)過程中使用的css中的px

          設(shè)備像素比(device pixel radio)

          設(shè)備像素比=物理像素 / 設(shè)備獨立像素,單位是dpr?。╠evice pixel radio)

          Retina屏幕

          所謂“Retina”是一種顯示標(biāo)準(zhǔn),是把更多的像素點壓縮至一塊屏幕里,從而達到更高的分辨率并提高屏幕顯示的細膩程度。也被稱為視網(wǎng)膜顯示屏 ——百度百科

          因為Retina屏幕的出現(xiàn),在pc端默認情況下,css中的1px等于1物理像素,但在移動端1px不一定等于1物理像素,比如說iPhone的設(shè)備獨立像素是375 667,因為它使用了Retina屏幕,他的dpr是2,所以iPhone 6 的物理像素為 750 1334

          在不同的屏幕上(普通屏幕 vs retina屏幕),css中1px所呈現(xiàn)的大小(物理尺寸)是一致的,不同的是1px所對應(yīng)的物理像素個數(shù)是不一致的。

          在普通屏幕下,1px 對應(yīng) 1個物理像素(1:1)。 在Retina屏幕下(dpr=2),1px對應(yīng) 2x2個物理像素(1:4)。

          你會發(fā)現(xiàn),在移動端開發(fā)中使用了圖片(img標(biāo)簽),2倍圖要比1倍圖清晰,就是這個緣故

          px

          默認情況下像素px是相對于屏幕分辨率而言,比如說我們的屏幕分辨率是1440 X 900,說的就是像素1440px X 900px;

          這里會遇到另一種情況

          ### 瀏覽器縮放

          縮放是縮放CSS像素(縮放比例為1時,一個CSS像素等于一個屏幕像素),就是在屏幕分辨率不變的情況下,用戶對瀏覽進行了縮放

          強調(diào)一點,用戶的縮放行為是對瀏覽器進行的,縮放的是css像素,而非分辨率,分辨率是屏幕的分辨率,不論你怎么縮放當(dāng)前頁面,屏幕分辨率都不會改變

          我們知道在移動端可以在一定程度上控制用戶的縮放行為,也可以禁止用戶縮放

          <meta name="viewport" content="width=device-width,initial-scale=1.0">
          

          content屬性值 :

          1. width:可視區(qū)域的寬度,值可為數(shù)字或關(guān)鍵詞device-width
          2. height:可視區(qū)域的高度,值可為數(shù)字或關(guān)鍵詞device-height
          3. intial-scale:頁面首次被顯示是可視區(qū)域的縮放級別,取值1.0則頁面按實際尺寸顯示,無任何縮放
          4. maximum-scale=1.0, minimum-scale=1.0;可視區(qū)域的縮放級別,
          5. maximum-scale用戶可將頁面放大的程序,1.0將禁止用戶放大到實際尺寸之上。
          6. user-scalable:是否可對頁面進行縮放,no 禁止縮放

          但是在pc端就麻煩了

          windows:

          • ctrl + +/-
          • ctrl + 滾輪
          • 瀏覽器菜單欄

          mac:

          • cammond + +/-
          • 瀏覽器菜單欄

          由于瀏覽器菜單欄屬于系統(tǒng)軟件權(quán)限,沒發(fā)控制,我們可以通過js控制ctrl/cammond + +/- 或 Windows下ctrl + 滾輪 縮放頁面的情況

          em

          本人在實際開發(fā)過程中并沒有使用過em單位,但是后面要說的rem是基于em的,所以,對em進行簡單介紹

          em 是相對長度單位。相對于當(dāng)前對象內(nèi)文本的字體尺寸。如當(dāng)前對行內(nèi)文本的字體尺寸未被人為設(shè)置,則相對于瀏覽器的默認字體尺寸。

          • em的值并不是固定的;
          • em會繼承父級元素的字體大小;
          • 任意瀏覽器的默認字體高都是16px。所有未經(jīng)調(diào)整的瀏覽器都符合: 1em=16px。body選擇器中聲明Font-size=62.5%<==>1em=10px。

          看個栗子吧

          <body>
           <style>
           html {
           font-size: 50px;
           }
          
           .my-div {
           width: 100%;
           height: 500px;
           margin-top: 50px;
           background-color: gray;
           font-size: 40px;
           }
          
           .my-div .parent-font {
           font-size: 30px;
           }
          
           .my-div .parent-font .child-font {
           font-size: 0.5em;
           }
           </style>
           <div class="my-div">
           <p class="parent-font">
           我是父級文字
           <span class="child-font">我是子級文字</span>
           </p>
           </div>
          </body>
          

          html代碼中,

          第一級,html的 font-size: 50px;

          第二級,my-div 的 font-size: 40px;

          第三級,parent-font 的 font-size:30px;

          第四級,child-font 的 font-size: 0.5em;

          我們通過瀏覽器查看,發(fā)現(xiàn)第四級的fong-size為15px;

          我們?nèi)∠谌塸arent-font 的字體大小

          我們通過瀏覽器查看,發(fā)現(xiàn)第四級的fong-size為20px;

          當(dāng)我們?nèi)∠谌塮ont-size后,第三級的字體大小為40px;

          所以我們說em的字體大小不是固定的,em的大小取決于父級的字體大小

          當(dāng)父級的字體大小為20px,子級的1em就是20px

          當(dāng)父級的字體大小為30px,子級的1em就是30px

          那么說font-size存在著繼承父級的特點

          我們在第一級html中設(shè)置font-size,第二級繼承第一級,第三級繼承第二級,第四級繼承第三級,以此類推

          每一級都繼承自它的父級,也就是說每一級的em所代表的px大小都不是固定的,因為他們的父級不是同一個,所以em的應(yīng)用場景并不多。

          那么如果是em的都繼承自同一個地方,是不是可以解決很多問題呢?

          這時候rem出現(xiàn)了

          rem

          rem 是CSS3的一個相對單位(root em,根em)

          使用rem為元素設(shè)定字體大小時,仍然是相對大小,但相對的只是HTML根元素

          只要html的font-size大小不變,1rem所代表的font-size大小就不會變,rem只取決于html的font-size

          rem解決了哪些問題

          移動設(shè)備的寬度是各種各樣的,每個設(shè)備的dpr也不同,換句話說就是不同設(shè)備每一行的物理像素數(shù)不同,能顯示的css的px數(shù)也不同,

          如果我們寫一個div,寬度是375px,375px在這個屏幕(iPhone6)上是剛剛滿屏,因為這個屏幕寬度剛剛是375px( 設(shè)備獨立像素),

          當(dāng)我們換另一個寬度是414px的設(shè)備(iPhone6Plus)時,這個寬度375px的div就無法鋪滿這個屏幕,同樣的當(dāng)換一個iPhone5(320px),又會出現(xiàn)滾動條,安卓機的寬度更是五花八門,使用media媒體查詢不靠譜,因為它不能覆蓋所有的機型寬度

          我們之前說rem的大小是相對于html的font-size的,如果html的font-size根據(jù)不同設(shè)備的寬度做動態(tài)計算,問題就會得到解決

          我們寫頁面都是根據(jù)UI設(shè)計稿來做的,我們假設(shè)UI設(shè)計稿的寬度是750px(750px是常規(guī)寬度,當(dāng)然也可以是640px或是其他寬度,但是整個項目,寬度必須統(tǒng)一),唯一不變就是就屏幕寬度,我們的html的font-size(rem)只取決于設(shè)備寬度

          于是

          document.documentElement.style.fontSize=100 * ( document.documentElement.clientWidth / 750) + 'px'
          

          html的font-size:document.documentElement.style.fontSize

          設(shè)備的寬度:document.documentElement.clientWidth

          750:UI設(shè)計稿的寬度

          為了方便計算我們將font-size x 100,方便計算(乘100不是必須的,我接觸過一些項目就不是乘以100,但是UI設(shè)計稿中使用了sketch做了動態(tài)計算,但我還是建議乘100,不然遇到psd的設(shè)計圖就很麻煩了)

          對上面的js做些完善

          const fontFun=function () {
           let docEl=document.documentElement
           let resizeEvt='orientationchange' in window ? 'orientationchange' : 'resize'
           const recalc=function () {
           let clientWidth=docEl.clientWidth
           if (!clientWidth) return
           docEl.style.fontSize=100 * (clientWidth / 750) + 'px'
           }
           if (!document.addEventListener) return
           window.addEventListener(resizeEvt, recalc, false)
           window.addEventListener('pageshow', recalc, false)
           document.addEventListener('DOMContentLoaded', recalc, false)
          }
          export {
           fontFun
          }
          

          對以上代碼不做過多解釋

          也可以這樣寫

          (function(doc, win) {
           var docEl=doc.documentElement,
           resizeEvt='orientationchange' in window ? 'orientationchange' : 'resize',
           recalc=function() {
           var clientWidth=docEl.clientWidth
           if (!clientWidth) return
           docEl.style.fontSize=100 * (clientWidth / 750) + 'px'
           }
           if (!doc.addEventListener) return
           win.addEventListener(resizeEvt, recalc, false)
           win.addEventListener('pageshow', recalc, false)
           doc.addEventListener('DOMContentLoaded', recalc, false)
          })(document, window)
          

          iPhone5(320px)下html的font-size:42.6667px,1rem=42.6667px

          iPhone6(375px)下html的font-size:50px,1rem=50px

          iPhone6Plus(414px)下html的font-size:55.2px,1rem=55.2px

          rem是繼承自html的font-size,但是小程序中沒有html,那怎么辦呢?

          rpx

          我不基于html的font-size了,我基于一個別的值就行了,你也不需要計算這個值,我給你計算了,這就是rpx。

          最終的效果就是,你開發(fā)時在iphon6的設(shè)計稿上量了多少px,就寫多少rpx就行了,完美適配,perfect!


          主站蜘蛛池模板: 亚洲区精品久久一区二区三区| 人妻体内射精一区二区三区| 日韩精品无码Av一区二区| 精品人无码一区二区三区| 一区二区在线电影| 国产福利一区二区三区| 精品国产一区二区三区香蕉| 国产av一区最新精品| 无码AⅤ精品一区二区三区| 2014AV天堂无码一区| 亚洲狠狠狠一区二区三区| 日韩在线一区视频| 精品免费久久久久国产一区 | 亚洲日韩精品国产一区二区三区| 亚洲AV无码一区二区三区网址 | 亚洲AV无码一区二区乱孑伦AS| 亚洲一区在线免费观看| 国产一区二区三区不卡在线看| 国产高清精品一区| 精品国产乱子伦一区二区三区| 日本一区二区三区在线网| 奇米精品视频一区二区三区| 国产精品亚洲一区二区三区在线观看 | 久久久久人妻精品一区蜜桃| 亚洲Av无码国产一区二区 | 国产亚洲一区二区三区在线不卡 | 国产精品久久久久久麻豆一区| 一区二区三区免费视频网站| 久久久无码一区二区三区| 亚洲高清偷拍一区二区三区| 精品爆乳一区二区三区无码av| 国产激情一区二区三区| 在线精品亚洲一区二区| 久久综合精品国产一区二区三区| 国产福利91精品一区二区三区 | 国精产品一区一区三区免费视频 | 色综合久久一区二区三区| 无码国产精品一区二区免费模式| 国产精品成人99一区无码| 亚洲福利电影一区二区?| 国产在线精品一区二区三区不卡|