方 案 | 實(shí)現(xiàn)方式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|---|
vm vh | 1.按照設(shè)計(jì)稿的尺寸,將px按比例計(jì)算轉(zhuǎn)為vw和vh | 1.可以動(dòng)態(tài)計(jì)算圖表的寬高,字體等,靈活性較高 2.當(dāng)屏幕比例跟 ui 稿不一致時(shí),不會(huì)出現(xiàn)兩邊留白情況 | 1.每個(gè)圖表都需要單獨(dú)做字體、間距、位移的適配,比較麻煩 |
scale | 1.通過(guò) scale 屬性,根據(jù)屏幕大小,對(duì)圖表進(jìn)行整體的等比縮放 | 1.代碼量少,適配簡(jiǎn)單2.一次處理后不需要在各個(gè)圖表中再去單獨(dú)適配 3.文字,圖片等大小均能自動(dòng)適配 | 1.因?yàn)槭歉鶕?jù) ui 稿等比縮放,當(dāng)大屏跟 ui 稿的比例不一樣時(shí),會(huì)出現(xiàn)周邊留白情況2.當(dāng)縮放比例過(guò)大時(shí)候,字體會(huì)有一點(diǎn)點(diǎn)模糊,就一點(diǎn)點(diǎn)3.當(dāng)縮放比例過(guò)大時(shí)候,事件熱區(qū)會(huì)偏移。 |
插件v-scale-screen | 是使用 css 屬性 transform 實(shí)現(xiàn)縮放效果的一個(gè)大屏自適應(yīng)組件,通過(guò) scale 進(jìn)行等比例計(jì)算,達(dá)到等比例縮放的效果 | 可以通過(guò)api調(diào)整原稿的寬高 |
方案一:vw vh
1.當(dāng)屏幕正好為16:9的時(shí)候
2.當(dāng)屏幕的尺寸比例大于 16:9 (左右拉長(zhǎng))
3.當(dāng)屏幕的尺寸比例小于 16:9 時(shí)(左右變窄或者上下拉高)
實(shí)現(xiàn)方法:
css 方案 - sass
utils.scss
// 使用 scss 的 math 函數(shù),https://sass-lang.com/documentation/breaking-changes/slash-div
@use "sass:math";
// 默認(rèn)設(shè)計(jì)稿的寬度
$designWidth: 1920;
// 默認(rèn)設(shè)計(jì)稿的高度
$designHeight: 1080;
// px 轉(zhuǎn)為 vw 的函數(shù)
@function vw($px) {
@return math.div($px, $designWidth) * 100vw;
}
// px 轉(zhuǎn)為 vh 的函數(shù)
@function vh($px) {
@return math.div($px, $designHeight) * 100vh;
}
復(fù)制代碼
路徑配置只需在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 函數(shù),將像素值傳進(jìn)去,得到的就是具體的 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";
// 默認(rèn)設(shè)計(jì)稿的寬度
@designWidth: 1920;
// 默認(rèn)設(shè)計(jì)稿的高度
@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 函數(shù),將像素值傳進(jìn)去,得到的就是具體的 vw vh單位
*/
.box{
.px2vw(width, 300);
.px2vh(height, 100);
.px2font(16);
.px2vw(margin-left, 300);
.px2vh(margin-top, 100);
background-color: black;
}
</style>
定義 js 樣式處理函數(shù)
// 定義設(shè)計(jì)稿的寬高
const designWidth = 1920;
const designHeight = 1080;
// px轉(zhuǎn)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';
};
屏幕變化后,圖表自動(dòng)調(diào)整
這種使用方式有個(gè)弊端,就是屏幕尺寸發(fā)生變化后,需要手動(dòng)刷新一下才能完成自適應(yīng)調(diào)整
為了解決這個(gè)問(wèn)題,你需要在各個(gè)圖表中監(jiān)聽(tīng)頁(yè)面尺寸變化,重新調(diào)整圖表,在 vue 項(xiàng)目中,也可以借助element-resize-detector,最好封裝個(gè) 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();
};
// 監(jiān)聽(tīng)綁定的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 切換動(dòng)態(tài)更新圖表數(shù)據(jù),在更新數(shù)據(jù)時(shí)一定不要用 echarts 的 dispose 方法先將圖表移除,再重新繪制,因?yàn)?resize 指令中掛載到的圖表實(shí)例還是舊的,就監(jiān)聽(tīng)不到新的 chart 元素的 resize 了,更新數(shù)據(jù)只需要用 chart 的 setOption 方法重新設(shè)置配置項(xiàng)即可。
解決方案二
1.在echarts中可以echarts.init(chatDom).resize()來(lái)解決寬高的自適應(yīng)問(wèn)題
let chatDom = document.getElementById('main');
let myChart = this.$echarts.init(chatDom);
//根據(jù)父盒子的尺寸調(diào)整echarts的大小
setTimeout(() => {
window.addEventListener('resize', () => {
this.$echarts.init(chatDom).resize();
});
}, 20);
2.在DataV中可以添加key來(lái)解決
<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
通過(guò) css 的 scale 屬性,根據(jù)屏幕大小,用js監(jiān)測(cè)屏幕的大小變化對(duì)圖表進(jìn)行整體的等比縮放,從而達(dá)到自適應(yīng)效果
當(dāng)屏幕的尺寸比例剛好是 16:9 時(shí),頁(yè)面能剛好全屏展示,內(nèi)容占滿(mǎn)顯示器
當(dāng)屏幕尺寸比例大于 16:9 時(shí),上下左右留白,左右占滿(mǎn)并居中,顯示比例保持 16:9
當(dāng)屏幕尺寸比例大于 16:9 時(shí),頁(yè)面左右留白,上下占滿(mǎn)并居中,顯示比例保持 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() {
// 初始化自適應(yīng) ----在剛顯示的時(shí)候就開(kāi)始適配一次
this.handleScreenAuto();
// 綁定自適應(yīng)函數(shù) ---防止瀏覽器欄變化后不再適配
window.onresize = () => this.handleScreenAuto();
},
deleted() {
window.onresize = null;
},
methods: {
// 數(shù)據(jù)大屏自適應(yīng)函數(shù)
handleScreenAuto() {
const designDraftWidth = 1920; //設(shè)計(jì)稿的寬度
const designDraftHeight = 1080; //設(shè)計(jì)稿的高度
// 根據(jù)屏幕的變化適配的比例
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>
/*
除了設(shè)計(jì)稿的寬高是根據(jù)您自己的設(shè)計(jì)稿決定以外,其他復(fù)制粘貼就完事
*/
h1 {
color: red;
font-size: 50px;
}
.screen-root {
height: 100vh;
width: 100vw;
.screen {
display: inline-block;
width: 1920px; //設(shè)計(jì)稿的寬度
height: 1080px; //設(shè)計(jì)稿的高度
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
它其實(shí)也是通過(guò) scale 進(jìn)行等比例計(jì)算放大和縮小的,和方案二的原理是一樣的,還可以通過(guò)api調(diào)整樣式,源碼地址和對(duì)應(yīng)的API
使用方法:
1.vue2請(qǐng)使用v-scale-screen@1.0.0版本,vue3請(qǐng)使用v-scale-screen@2.0.0版本文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-786383.html
npm install v-scale-screen@1.0.0 -save
# or
yarn add v-scale-screen
2.使用-vue2中使用插件導(dǎo)入,vue3以組件導(dǎo)入文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-786383.html
vue2
// main.js
import VScaleScreen from 'v-scale-screen'
Vue.use(VScaleScreen)
組件內(nèi)使用
//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>
- vue2演示地址
- vue3演示地址
到了這里,關(guān)于前端大屏常用的幾種適配方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!