前端大屏常用的几种适配方案
Posted 鲁少聚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端大屏常用的几种适配方案相关的知识,希望对你有一定的参考价值。
方 案 | 实现方式 | 优点 | 缺点 |
---|---|---|---|
vm vh | 1.按照设计稿的尺寸,将px按比例计算转为vw和vh | 1.可以动态计算图表的宽高,字体等,灵活性较高 2.当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况 | 1.每个图表都需要单独做字体、间距、位移的适配,比较麻烦 |
scale | 1.通过 scale 属性,根据屏幕大小,对图表进行整体的等比缩放 | 1.代码量少,适配简单2.一次处理后不需要在各个图表中再去单独适配 3.文字,图片等大小均能自动适配 | 1.因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况2.当缩放比例过大时候,字体会有一点点模糊,就一点点3.当缩放比例过大时候,事件热区会偏移。 |
插件v-scale-screen | 是使用 css 属性 transform 实现缩放效果的一个大屏自适应组件,通过 scale 进行等比例计算,达到等比例缩放的效果 | 可以通过api调整原稿的宽高 |
方案一:vw vh
1.当屏幕正好为16:9的时候
2.当屏幕的尺寸比例大于 16:9 (左右拉长)
3.当屏幕的尺寸比例小于 16:9 时(左右变窄或者上下拉高)
实现方法:
css 方案 - sass
utils.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里配置一下utils.scss的路径,就可以全局使用了
vue.config.js
module.exports =
css:
loaderOptions:
sass:
prependData: `@import "@/assets/css/utils.scss";`
,
在 .vue 中使用
<template>
<div class="box">
</div>
</template>
<script>
export default
name: "Box",
</script>
<style lang="scss" scoped="scoped">
/*
直接使用 vw 和 vh 函数,将像素值传进去,得到的就是具体的 vw vh 单位
*/
.box
width: vw(300);
height: vh(100);
font-size: vh(16);
background-color: black;
margin-left: vw(10);
margin-top: vh(10);
border: vh(2) solid red;
</style>
css 方案 - less
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;
路径配置在vue.config.js里配置一下utils.less
<style lang="less" scoped="scoped">
/*
直接使用 vw 和 vh 函数,将像素值传进去,得到的就是具体的 vw vh单位
*/
.box
.px2vw(width, 300);
.px2vh(height, 100);
.px2font(16);
.px2vw(margin-left, 300);
.px2vh(margin-top, 100);
background-color: black;
</style>
定义 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 项目中,也可以借助element-resize-detector,最好封装个 resize 的指令,在各图表中就只要使用该指令就可以了,毕竟作为程序员,能偷懒就偷懒
解决方案一
- 安装 element-resize-detector
npm install element-resize-detector --save
- 封装成自定义指令使用
// directive.js
import * as ECharts from "echarts";
import elementResizeDetectorMaker from "element-resize-detector";
import Vue from "vue";
const HANDLER = "_vue_resize_handler";
function bind(el, binding)
el[HANDLER] = binding.value
? binding.value
: () =>
let chart = ECharts.getInstanceByDom(el);
if (!chart)
return;
chart.resize();
;
// 监听绑定的div大小变化,更新 echarts 大小
elementResizeDetectorMaker().listenTo(el, el[HANDLER]);
function unbind(el)
// window.removeEventListener("resize", el[HANDLER]);
elementResizeDetectorMaker().removeListener(el, el[HANDLER]);
delete el[HANDLER];
// 自定义指令:v-chart-resize 示例:v-chart-resize="fn"
Vue.directive("chart-resize", bind, unbind );
- main.js 中引入
import '@/directive/directive';
- html 代码中使用
<template>
<div class="linechart">
<div ref="chart" v-chart-resize class="chart"></div>
</div>
</template>
这里要注意的是,图表中如果需要 tab 切换动态更新图表数据,在更新数据时一定不要用 echarts 的 dispose 方法先将图表移除,再重新绘制,因为 resize 指令中挂载到的图表实例还是旧的,就监听不到新的 chart 元素的 resize 了,更新数据只需要用 chart 的 setOption 方法重新设置配置项即可。
解决方案二
1.在echarts中可以echarts.init(chatDom).resize()来解决宽高的自适应问题
let chatDom = document.getElementById('main');
let myChart = this.$echarts.init(chatDom);
//根据父盒子的尺寸调整echarts的大小
setTimeout(() =>
window.addEventListener('resize', () =>
this.$echarts.init(chatDom).resize();
);
, 20);
2.在DataV中可以添加key来解决
<dv-water-level-pond :config="config2" :key="key" ref="pie2" />
data()
return
key: 1
,
mounted()
this.pieOutlineFunc();
,
methods:
pieOutlineFunc()
var _this = this;
window.addEventListener('resize', function (e)
_this.$nextTick(() =>
console.log(_this.$refs.pie2);
_this.key++;
);
);
方案二:csale
通过 css 的 scale 属性,根据屏幕大小,用js监测屏幕的大小变化对图表进行整体的等比缩放,从而达到自适应效果
当屏幕的尺寸比例刚好是 16:9 时,页面能刚好全屏展示,内容占满显示器
当屏幕尺寸比例大于 16:9 时,上下左右留白,左右占满并居中,显示比例保持 16:9
当屏幕尺寸比例大于 16:9 时,页面左右留白,上下占满并居中,显示比例保持 16:9
上代码
html
<template>
<div class="screen-root">
<div class="screen" id="screen">
<div class="div1">
<h1>11111111111</h1>
</div>
<div class="div2">
<h1>2222222222</h1>
</div>
<div class="div3">
<h1>3333333333</h1>
</div>
</div>
</div>
</template>
js
<script>
export default
mounted()
// 初始化自适应 ----在刚显示的时候就开始适配一次
this.handleScreenAuto();
// 绑定自适应函数 ---防止浏览器栏变化后不再适配
window.onresize = () => this.handleScreenAuto();
,
deleted()
window.onresize = null;
,
methods:
// 数据大屏自适应函数
handleScreenAuto()
const designDraftWidth = 1920; //设计稿的宽度
const designDraftHeight = 1080; //设计稿的高度
// 根据屏幕的变化适配的比例
const scale =
document.documentElement.clientWidth / document.documentElement.clientHeight <
designDraftWidth / designDraftHeight
? document.documentElement.clientWidth / designDraftWidth
: document.documentElement.clientHeight / designDraftHeight;
// 缩放比例
document.querySelector('#screen').style.transform = `scale($scale) translate(-50%,-50%)`;
return 1;
;
</script>
css
<style lang="scss" scoped>
/*
除了设计稿的宽高是根据您自己的设计稿决定以外,其他复制粘贴就完事
*/
h1
color: red;
font-size: 50px;
.screen-root
height: 100vh;
width: 100vw;
.screen
display: inline-block;
width: 1920px; //设计稿的宽度
height: 1080px; //设计稿的高度
transform-origin: 0 0;
position: absolute;
left: 50%;
top: 50%;
border: 2px solid rgb(31, 210, 145);
box-sizing: border-box;
display: flex;
.div1
background-color: #fff;
height: 100%;
text-align: center;
flex: 0 1 30%;
.div2
background-color: rgb(133, 14, 14);
height: 100%;
text-align: center;
flex: 0 1 40%;
.div3
background-color: rgb(61, 6, 188);
height: 100%;
text-align: center;
flex: 0 1 30%;
</style>
方案三:插件v-scale-screen
它其实也是通过 scale 进行等比例计算放大和缩小的,和方案二的原理是一样的,还可以通过api调整样式,源码地址和对应的API
使用方法:
1.vue2请使用v-scale-screen@1.0.0版本,vue3请使用v-scale-screen@2.0.0版本
npm install v-scale-screen@1.0.0 -save
# or
yarn add v-scale-screen
2.使用-vue2中使用插件导入,vue3以组件导入
vue2
// main.js
import VScaleScreen from 'v-scale-screen'
Vue.use(VScaleScreen)
组件内使用
//html
<v-scale-screen width="1920" height="1080" :boxStyle="boxStyle">
<div>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
</div>
</v-scale-screen>
//js
data()
return
boxStyle:
backgroundColor: 'green'
,
vue3
<v-scale-screen width="1920" height="1080">
<div>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
<v-chart>....</v-chart>
</div>
</v-scale-screen>
<script>
import VScaleScreen from 'v-scale-screen'
export default
components:
VScaleScreen
</script>
vue适配不同屏幕大小_移动端适配的几种方案
适配思路
设计稿(750*1334) ---> 开发 ---> 适配不同的手机屏幕,使其显得合理
原则
- 开发时方便,写代码时设置的值要和标注的 160px 相关
- 方案要适配大多数手机屏幕,并且无 BUG
- 用户体验要好,页面看着没有不适感
思路
- 写页面时,按照设计稿写固定宽度,最后再统一缩放处理,在不同手机上都能用
- 按照设计稿的标准开发页面,在手机上部分内容根据屏幕宽度等比缩放,部分内容按需要变化,需要缩放的元素使用 rem, vw 相对单位,不需要缩放的使用 px
- 固定尺寸+弹性布局,不需要缩放
viewport 适配
根据设计稿标准(750px 宽度)开发页面,写完后页面及元素自动缩小,适配 375 宽度的屏幕
在 head 里设置如下代码
<meta name="viewport" content="width=750,initial-scale=0.5">
initial-scale = 屏幕的宽度 / 设计稿的宽度
为了适配其他屏幕,需要动态的设置 initial-scale 的值
<head> <script> const WIDTH = 750 const mobileAdapter = () => { let scale = screen.width / WIDTH let content = `width=${WIDTH}, initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}` let meta = document.querySelector(\'meta[name=viewport]\') if (!meta) { meta = document.createElement(\'meta\') meta.setAttribute(\'name\', \'viewport\') document.head.appendChild(meta) } meta.setAttribute(\'content\',content) } mobileAdapter() window.onorientationchange = mobileAdapter //屏幕翻转时再次执行 </script> </head>
缺点就是边线问题,不同尺寸下,边线的粗细是不一样的(等比缩放后),全部元素都是等比缩放,实际显示效果可能不太好
vw 适配(部分等比缩放)
- 开发者拿到设计稿(假设设计稿尺寸为750px,设计稿的元素标注是基于此宽度标注)
- 开始开发,对设计稿的标注进行转换,把px换成vw。比如页面元素字体标注的大小是32px,换成vw为 (100/750)*32 vw
- 对于需要等比缩放的元素,CSS使用转换后的单位
- 对于不需要缩放的元素,比如边框阴影,使用固定单位px
关于换算,为了开发方便,利用自定义属性,CSS变量
<head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> <script> const WIDTH = 750 //:root { --width: 0.133333 } 1像素等于多少 vw document.documentElement.style.setProperty(\'--width\', (100 / WIDTH)) </script> </head>
注意此时,meta 里就不要去设置缩放了
业务代码里就可以写
header { font-size: calc(28vw * var(--width)) }
实现了按需缩放
rem 适配
- 开发者拿到设计稿(假设设计稿尺寸为750px,设计稿的元素标是基于此宽度标注)
- 开始开发,对设计稿的标注进行转换
- 对于需要等比缩放的元素,CSS使用转换后的单位
- 对于不需要缩放的元素,比如边框阴影,使用固定单位px
假设设计稿的某个字体大小是 40px, 手机屏幕上的字体大小应为 420/750*40 = 22.4px (体验好),换算成 rem(相对于 html 根节点,假设 html 的 font-size = 100px,)则这个字体大小为 0.224 rem
写样式时,对应的字体设置为 0.224 rem 即可,其他元素尺寸也做换算...
但是有问题
举个 ,设计稿的标注 是40px,写页面时还得去做计算,很麻烦(全部都要计算)
能不能规定一下,看到 40px ,就应该写 40/100 = 0.4 rem,这样看到就知道写多少了(不用计算),此时的 html 的 font-size 就不能是 100px 了,应该为 (420*100)/750 = 56px,100为我们要规定的那个参数
根据不同屏幕宽度,设置 html 的 font-size 值
<head> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> <script> const WIDTH = 750 //设计稿尺寸 const setView = () => { document.documentElement.style.fontSize = (100 * screen.width / WIDTH) + \'px\' } window.onorientationchange = setView setView() </script> </head>
对于需要等比缩放的元素,CSS使用转换后的单位
header { font-size: .28rem; }
对于不需要缩放的元素,比如边框阴影,使用固定单位px
header > span.active { color: #fff; border-bottom: 2px solid rgba(255, 255, 255, 0.3); }
假设 html 的 font size = 1px 的话,就可以写 28 rem 了,更方便了,但是浏览器对字体大小有限制,设为 1px 的话,在浏览器中是失效的,会以 12px(或者其他值) 做一个计算 , 就会得到一个很夸张的结果,所以可以把 html 写的大一些
使用 sass 库时
JS 处理还是一样的,但看着好看些
@function px2rem($px) { @return $px * 1rem / 100; } header { font-size: px2rem(28); }
以上的三种适配方案,都是等比缩放,放到 ipad 上时(设计稿以手机屏幕设计的),页面元素会很大很丑,有些场景下,并不需要页面整体缩放(viewport 自动处理的也很好了),所以有时只需要合理的布局即可。
弹性盒适配(合理布局)
<meta name="viewport" content="width=device-width">
使用 flex 布局
section {
display: flex;
}
总结一下,什么样的页面需要做适配(等比缩放)呢
- 页面中的布局是栅格化的
换了屏幕后,到底有多宽多高很难去做设置,整体的都需要改变,所以需要整体的缩放
- 头屏大图,宽度自适应,高度固定的话,对于不同的屏幕,形状就会发生改变(放到ipad上就变成长条了),宽度变化后,高度也要保持等比例变化
以上所有的适配都是宽度的适配,但是在某些场景下,也会出现高度的适配
比如大屏,需要适配很多的电视尺寸,要求撑满屏幕,不能有滚动条,此时若换个屏幕
此时需要考虑小元素用 vh, 宽和高都用 vh 去表示,中间的大块去自适应,这就做到了大屏的适配,屏幕变小了,整体变小了(体验更好),中间这块撑满了屏幕
对于更复杂的场景,需要更灵活考虑,没有一种适配方式可以囊括所有场景。
以上是关于前端大屏常用的几种适配方案的主要内容,如果未能解决你的问题,请参考以下文章