切換語言為:簡體

vue3+webpack5+sass搭建自適應大屏專案

  • 爱糖宝
  • 2024-09-23
  • 2048
  • 0
  • 0

近每個前端都會經歷大屏的開發,不管是投屏到4k顯示器還是投屏到100寸的展廳裡,都要保證頁面的自適應。這裏我實現的樣式用sass語言。

大屏自適應

全域性global.scss樣式部分直接上程式碼:

@use "sass:math";

// 預設設計稿的寬度和高度
$default-design-width: 3840px;
$default-design-height: 2160px;

// 根據螢幕解析度調整的寬度和高度
$designWidth: $default-design-width;
$designHeight: $default-design-height;

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

// px 轉為 vh 的函式
@function vh($px) {
  @return math.div($px, $designHeight) * 100vh;
}
// 根據螢幕解析度調整設計稿尺寸
@media (max-width: 3840px) and (max-height: 2160px) {
  $designWidth: 3840px;
  $designHeight: 2160px;
}

@media (max-width: 2560px) and (max-height: 1440px) {
  $designWidth: 2560px;
  $designHeight: 1440px;
}

@media (max-width: 1920px) and (max-height: 1080px) {
  $designWidth: 1920px;
  $designHeight: 1080px;
}

@media (max-width: 1366px) and (max-height: 768px) {
  $designWidth: 1366px;
  $designHeight: 768px;
}

body{
  width: 100vw;
  height: 100vh;
  background-color: #000000;
  box-sizing: border-box;
  overflow-x: hidden;
  font-family: "AlibabaPuHuiTi-Regular";
}
...

設計師給我的稿子是按照4k顯示屏開發的,所有的寬高都是按照3840px*2160px來計算的,所以這裏給了一個預設的寬高,然後根據螢幕的自適應等比計算。

比如:

<style scoped>
    .grid {
          display: grid;
          grid-template-columns:  vw(320px) vw(455px);
          grid-template-rows: repeat(2,vh(120px));
          gap: vw(15px);
          margin-left: vw(20px);
          .grid-item {
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: right;
            padding: vh(9px) vw(20px) ;
          }
      }
      ...
</style>

這裏設計稿給到的寬320px高120px,這邊用vw(320px),vh(120px)去等比計算,省去了很多麻煩,跟著設計稿畫頁面就完事了。

炫酷效果

無縫滾動

然後裡面很多動效,比如常用的表格輪博滾動,vue3-seamless-scroll來實現,Vue3.0 無縫滾動元件,支援Vite2.0,支援服務端打包

詳情地址:www.npmjs.com/package/vue…

引入地圖,城市打點標記

html頁面引入

  <script src="//api.map.baidu.com/api?type=webgl&v=2.0&ak=xxxxxxxxxxxxx"></script>

業務程式碼使用

<template>
      <div id="mapMark"></div>
</template>
<script setup>
import {ref,reactive, watch,onMounted} from 'vue';
const initMap = async (city,markList) => {
      let Bmap = window.BMapGL
      var b = new Bmap.Map("mapMark")
      b.setMapStyleV2({     
        styleId: '1e3322xxxxxxxxxxxxxxx287b' //這裏是百度開發平臺的樣式生成的id
      });
      // b.centerAndZoom(new Bmap.Point(104.328743,32.917728), 6.6)   
      // b.setTilt(40); 
      b.enableScrollWheelZoom(true)
      if(markList && markList.length > 0){
        markList.forEach(async (item,index)=>{
          const loc = await getLocationByCityName(item + '市','中國');
          const marker= addIconByCity(loc);
          b.addOverlay(marker);
        })
      }
      const loc = await getLocationByCityName( '蘭州市','中國');
      b.centerAndZoom(new Bmap.Point(loc.lng, loc.lat), 7);
      b.setTilt(10); 
}
const getLocationByCityName = (city,country)=>{
    return new Promise((resolve, reject) => {
      let location = {};
      let Bmap = window.BMapGL;
      var b = new Bmap.Geocoder();
      b.getPoint(city + country, (res) => {
        if (res) {
          location.lat = res.lat;
          location.lng = res.lng;
          resolve(location); 
        } else {
          reject({});
        }
      });
    });
}
const addIconByCity = (location)=>{
      let Bmap = window.BMapGL;
      const pic = require('../images/mark.png');
      var icon = new Bmap.Icon(pic, new Bmap.Size(52, 52),{
        anchor: new Bmap.Size(30, 50), 
      });
      const cityPoint = new Bmap.Point(location.lng, location.lat);  
      var marker = new Bmap.Marker(cityPoint);
      marker.setIcon(icon);
      return marker
}
onMounted(()=>{
  const markList = ['北京','上海','無錫','廈門','成都','成都']
  initMap('成都',markList);
});
</script>
<style scoped>
  .mapMark{
    width: 100vw;
    height: 100vh;
    position: absolute;
    left: 0;
    top:0;
    z-index: 1;
    background-color: #000000;
  }
</style>

vue3+webpack5+sass搭建自適應大屏專案

echarts自適應

其它各種賊啦炫酷的圖表樣式用的是echarts,然後在js程式碼中調整自適應

const systemStaionEcharts = (data,total) => {
  try {
    const myChart = echarts.init(document.getElementById("pieEcharts"));
    window.addEventListener("resize", () => {
      myChart.resize();
    }, false);
    const option = pieEchartsOptions(data,total);
    myChart.setOption(option);
  } catch (e) {
    console.error(e)
  }
}

這裏也需要用js去動態計算echarts的細節樣式,這裏寫了一個utils.js工具函式

// 預設設計稿的寬度和高度
var defaultDesignWidth = 3840;
var defaultDesignHeight = 2160;
/**
 * 根據螢幕解析度計算調整後的寬度,保持16:9比例
 * @param {number} designWidth - 設計稿的寬度
 * @returns {number} 調整後的寬度
 */
function calculateWidth(designWidth) {
    // 獲取當前螢幕的寬度
    const screenWidth = window.innerWidth;
    const widthRatio = screenWidth / defaultDesignWidth;
    // 計算調整後的寬度
    const scaledWidth = designWidth * widthRatio;
    return scaledWidth;
}

/**
 * 根據螢幕解析度計算調整後的高度,保持16:9比例
 * @param {number} designHeight - 設計稿的高度
 * @returns {number} 調整後的高度
 */
function calculateHeight(designHeight) {
    // 獲取當前螢幕的寬度
    const screenHeight = window.innerHeight;
    const heightRatio = screenHeight / defaultDesignHeight;
    // 計算調整後的高度
    const scaledHeight = designHeight * heightRatio;
    return scaledHeight;
}
export {
    calculateWidth,
    calculateHeight
}

然後在檔案中引入函式,使用calculateWidth, calculateHeight去計算細節

import { calculateWidth, calculateHeight} from '../utils/scaleSizeToScreen';

export const pieEchartsOptions = () => {
    return {
        title: {
            subtext: '系統部署',
            textStyle: {
                fontSize: calculateWidth(49),
            },
            subtextStyle: {
                fontSize: calculateWidth(18),
            },
        },
        ...
    }
}

最後,大屏考慮到效能,還有很多地方做了一下最佳化,比如爲了保證頁面的穩定性,自己提前引入了一份靜態資料檔案供頁面渲染,減少介面請求的等待依賴,然後介面響應後再去動態調整。再比如實時資料用webSocket型別介面,然後多寫一些try catch防止髒資料渲染出現問題,能夠及時定位問題所在。還有圖片格式,要跟設計師保持溝通,在不影響美觀的情況下能有多小壓縮到多小,用小體積的檔案格式等等,最後把http1.1升級帶http2就完事了。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.