近每个前端都会经历大屏的开发,不管是投屏到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,支持服务端打包
引入地图,城市打点标记
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>
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就完事了。