一、目前市场上适配方案有两种;
vw、vh方案:
原理:按照设计稿的尺寸,将px按比例计算转为vw和vh;
优点:不会存在失真情况、可以动态计算图表的宽高,字体等,灵活性较高,当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况;
缺点:类似第三方echart图表都需要单独做字体、间距、位移的适配,比较麻烦
核心代码以sass为例
css
/*util.scss*/
@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;
}
然后页面中引入util.scss、将20px更换为vh(20)
css
@import '@/assets/style/util.scss';
.dateText {
padding-top: vh(20);
}
.weatherText {
padding-top: vh(32);
}
在js中使用到尺寸可以用下面这个工具方法去做转换
js
const styleUtil = {
// px转vw
px2vw: function (_px, unit) {
if (unit) {
return (_px * 100.0) / designWidth + unit;
}
return (_px * 100.0) / designWidth + 'vw';
},
// px转vh
px2vh: function (_px, unit) {
if (unit) {
return (_px * 100.0) / designHeight + unit;
}
return (_px * 100.0) / designHeight + 'vh';
},
};
chart 图表中的适配用以下方法、需要注意的是、在resize的时候、让echart也resize一下
js
const fitChartSize = (size, defaultHeight = 1080) => {
// 默认宽高问设计
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
console.log('clientHeight::: ', clientHeight);
if (!clientHeight) return size;
let scale = clientHeight / defaultHeight;
return Number((size * scale).toFixed(3));
};
缩放方案
原理:按照设计稿的尺寸布局,采用等比例缩放、在不同屏幕尺寸中将其通过放大缩小最外层的dom为一定比例、来保持原本布局;
优点:代码量少,适配简单 、一次处理后不需要在各个图表中再去单独适配;
缺点:如果缩放比例超过一定程度,字体图片等就会失真、会留白
核心代码
js
const usePreviewFitScale = (width, height, scaleDom, callback) => {
// * 画布尺寸(px)
const baseWidth = width;
const baseHeight = height;
// * 默认缩放值
const scale = {
width: 1,
height: 1,
};
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5));
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5));
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽 以高度为基准 需要保持比例的宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5));
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5));
const offsetW = ((window.innerWidth - window.innerHeight * baseProportion) / 2).toFixed(5);
scaleDom.style.transform = `translateX(${offsetW}px) scale(${scale.width}, ${scale.height})`;
} else {
// 表示更高 以宽度为基准 需要保持比例的高
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5));
scale.height = parseFloat((window.innerWidth / baseProportion / baseHeight).toFixed(5));
scaleDom.style.transform = `translateX(0px) scale(${scale.width}, ${scale.height})`;
}
if (callback) callback(scale);
}
};
const resize = throttle(() => {
calcRate();
}, 200);
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize);
};
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize);
};
return {
calcRate,
windowResize,
unWindowResize,
};
};
至于还有流传rem + vw vh的方案(我是直接舍弃的)
这个rem的方案是根据单个宽度来计算的,只能适配宽度缩放、而大屏是一屏展示、而且在类似echart图表中,还需要做vw vh的单独适配、也是直接舍弃
有的同学还说有设计外层盒子百分比、盒子内部图表大小固定;
这种方式怎么说呢,那就得UI配合给我们设计出对应的样式、而且这种不用动脑子想也是很丑啊、还是直接pass吧、大屏本身就是要做的好看
二、我们先搞清楚可视化大屏适配与传统后台管理系统适配的区别
后台管理系统适配: 只适配宽、当宽超出则换行展示、类似的layout组件、Row组件、flex布局的都是采用只适配宽的方式、而且内部尺寸大小固定;
可视化大屏适配:宽高都需适配、而且没有滚动条、一屏展示;
三、当然不管采用那种方式我们都要一客户需求基点、然后分析出对应的解决方式
1、 嵌入管理系统内部展示: 多数情况以非全屏展示
这种情况如果使用缩放形式、其实也可以、那得需要UI出图为实际空间占比的UI、否则当我们写完代码,因为底部程序坞和浏览器窗口操作栏的高度,导致缩放比大、就会凸显失真情况的产生,而且有留白
一般情况UI给的图就是1920*1080的尺寸比、当然如果客户要求不高、采用这种方式当然是最省事;
但如果客户要求高、还是老老实实的使用vw、vh
2、纯全屏显示:多数情况给定尺寸为大屏尺寸、全屏展示、不考虑程序坞、浏览器上方操作栏;
这种场景呢,就比较适合缩放、因为一般适配屏幕大小不会差太多、没有很多情况、即使失真、多数也在客户考虑范围之内;
因为vw vh方式,如果是正常布局的vw、vh和echart 高度比计算得出来的尺寸位置,可能会存在对不齐的情况、当然具体情况具体分析;