切换语言为:繁体

vue3+webpack5+sass搭建自适应大屏项目

  • 爱糖宝
  • 2024-09-23
  • 2047
  • 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.