1. 程式人生 > 其它 >大屏適配方案

大屏適配方案

一、問題引入:

視覺化資料大屏需要適配各種大屏尺寸 

1080P:1920*1080

2K:2560*1440 左右

4K:3840*2160 左右

8K:7680*4320 左右

二、適配方案分析

  • 如果想簡單,客戶能同意留白,選用 scale 即可
  • 如果需要相容不同比例的大屏,並且想在不同比例中都有比較好的效果,圖表佔滿螢幕,類似於移動端的響應式,可以採用 vm vh 的方案
  • 至於 rem,個人覺得就是 scale 和 vm vh 的綜合,最終的效果跟 scale 差不多

三、方案一

實現思路

按照設計稿的尺寸,將px按比例計算轉為vwvh,轉換公式如下

假設設計稿尺寸為 1920*1080(做之前一定問清楚 ui 設計稿的尺寸)

即:
網頁寬度
=1920px 網頁高度=1080px 我們都知道 網頁寬度=100vw 網頁寬度=100vh 所以,在 1920px*1080px 的螢幕解析度下 1920px = 100vw 1080px = 100vh 這樣一來,以一個寬 300px 和 200px 的 div 來說,其所佔的寬高,以 vw 和 vh 為單位,計算方式如下: vwDiv = (300px / 1920px ) * 100vw vhDiv = (200px / 1080px ) * 100vh 所以,就在 1920*1080 的螢幕解析度下,計算出了單個 div 的寬高 當螢幕放大或者縮小時,div 還是以 vw 和 vh 作為寬高的,就會自動適應不同解析度的螢幕

相關程式碼如下:

使用less方式:

1.安裝外掛:

npm i style-resources-loader --save-dev

2.新建utils.less檔案:

@charset "utf-8";

// 預設設計稿的寬度
@designWidth: 1920;

// 預設設計稿的高度
@designHeight: 1080;

.px2vw(@name, @px) {
    @{name}: (@px / @designWidth) * 100vw;
}

.px2vh(@name, @px) {
    @{name}: (@px / @designHeight) * 100vh;
}

.px2font(@px) {
    font
-size: (@px / @designWidth) * 100vw; } .px2vwCalc(@name, @px, @scale) { @{name}: calc(@scale - (@px / @designWidth) * 100vw); } .px2vhCalc(@name, @px, @scale) { @{name}: calc(@scale - (@px / @designHeight) * 100vh); } // padding margin簡寫 .px2pm(@name, @pxheight, @pxwidth) { @{name}: ((@pxheight / @designHeight) * 100vh) ((@pxwidth / @designWidth) * 100vw); }

3.路徑配置
vue.config.js裡配置一下utils.less

module.exports = {
    ...
    // 全域性配置utils.less
    pluginOptions: {
     "style-resources-loader": { 
            preProcessor: "less", 
            patterns: [ path.resolve(__dirname, "./src/assets/css/utils.less") ] 
        }
  }
}

網上查資料亦可使用

const path = require("path");

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  publicPath: "",
  configureWebpack: {
    name: "app name",
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
  },
  css: {
    // 全域性配置utils.scss
    loaderOptions: {
      less: {
        additionalData: `@import "@/styles/utils.less";`,
      },
    },
  },
};

4.在vue檔案中使用

.el-dialog__header {
            // padding: 24px;
            .px2vw(padding, 24);
            // padding-bottom: 20px;
            .px2vw(padding-bottom, 20);

            .el-dialog__headerbtn {
                // top: 20px;
                .px2vh(top, 20);
                // right: 20px;
                .px2vw(right, 20);
                // font-size: 16px;
                .px2font(16);
            }
        }

說明:如果報錯 .px2vw 為undefined說明全域性配置有問題,由於cli版本不同,安裝下面外掛即可解決

npm i vue-cli-plugin-style-resources-loader --save-dev

5.定義js樣式處理函式 util.js

// 定義設計稿的寬高
const designWidth = 1920;
const designHeight = 1080;

// px轉vw
export const px2vw = (_px) => {
    return (_px * 100.0) / designWidth + 'vw';
};

export const px2vh = (_px) => {
    return (_px * 100.0) / designHeight + 'vh';
};

export const px2font = (_px) => {
    return (_px * 100.0) / designWidth + 'vw';
};

全域性寫入vue原型

import { px2vw, px2vh, px2font } from './assets/utils'
Vue.prototype.$px2vw = px2vw
Vue.prototype.$px2vh = px2vh
Vue.prototype.$px2font = px2font

頁面或者js中使用

<el-dialog :width="$px2vw(800)"></el-dialog>

6.圖表字型、間距、位移等尺寸自適應

編寫 dataUtil.js 工具函式

// Echarts圖表字型、間距自適應
export const fitChartSize = (size,defalteWidth = 1920) => {
  let clientWidth = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
  if (!clientWidth) return size;
  let scale = (clientWidth / defalteWidth);
  return Number((size*scale).toFixed(3));
}

將函式掛載到原型上

import {fitChartSize} from '@src/utils/dataUtil.js'
Vue.prototype.fitChartSize = fitChartSize;

圖表配置options中使用

legend: {
                    // top: 15,
                    top: _this.fitChartSize(15),
                    // itemWidth: 8,
                    itemWidth: _this.fitChartSize(8),
                    // itemHeight: 8,
                    itemHeight: _this.fitChartSize(8),
                    textStyle: {
                        fontFamily: 'AlibabaPuHuiTi-Regular',
                        // fontSize: 14,
                        fontSize: _this.fitChartSize(14),
                        color: '#FFFFFF',
                        fontWeight: 400
                    }
                },
                grid: {
                    // left: 80,
                    left: _this.fitChartSize(80),
                    // right: 170,
                    right: _this.fitChartSize(170),
                    // bottom: 30,
                    bottom: _this.fitChartSize(30),
                    // top: 50
                    top: _this.fitChartSize(50)
                },

使用sass方式

util.scss

// 使用 scss 的 math 函式,https://sass-lang.com/documentation/breaking-changes/slash-div
@use "sass:math";

// 預設設計稿的寬度
$designWidth: 1920;
// 預設設計稿的高度
$designHeight: 1080;

// px 轉為 vw 的函式
@function vw($px) {
  @return math.div($px, $designWidth) * 100vw;
}

// px 轉為 vh 的函式
@function vh($px) {
  @return math.div($px, $designHeight) * 100vh;
}

路徑配置

vue.config.js配置

const path = require("path");

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  publicPath: "",
  configureWebpack: {
    name: "app name",
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
  },
  css: {
    // 全域性配置 utils.scs,詳細配置參考 vue-cli 官網
    loaderOptions: {
      sass: {
        prependData: `@import "@/styles/utils.scss";`,
      },
    },
  },
};

如若報錯undefined,需要安裝sass相關外掛,具體自行查閱資料