前言
开发过大屏的铁汁们应该知道,前期最头疼的就是大屏适配,由于大屏项目需要在市面上不是很常见的显示器上进行展示,所以要根据不同的尺寸进行适配,今天我将为大家分享的我使用的大屏适配方案,话不多说,直接上效果图。
效果图
上面所展示的只是其中一种模式,其中一共有四种模式,分别为1-居中留白(按比例伸缩);、2-居中留白(若不超出屏则不拉伸);、3-窄边铺满(长边滚动)、4-铺满全屏。
准备工作
首先,我们需要把使用到的依赖进行安装:
npm i element-resize-detector
npm i animejs
npm i jquery
然后,在vuex中定义以下变量和方法:
state: {
mode: 1, //1-居中留白(按比例伸缩); 2-居中留白(若不超出屏则不拉伸); 3-窄边铺满(长边滚动); 4-铺满全屏
exw: 40,
left: 0,
top: 0,
orderWork: {},
warn: {},
fontSize: 30,
},
mutations: {
increment(state, fs) {
state.fontSize = fs;
},
exMode(state, mode) {
state.mode = mode;
},
addExW(state, exw) {
state.exw = exw;
},
addLeft(state, left) {
state.left = left;
},
addTop(state, top) {
state.top = top;
},
},
最后,需要在main.js中定义我们需要用到的全局方法:
// 以下为vue3的写法
import ElementResizeDetectorMaker from "element-resize-detector";
import anime from "animejs";
import jquery from "jquery";
const app = createApp(App);
app.config.globalProperties.$erd = ElementResizeDetectorMaker();
app.config.globalProperties.$anime = anime;
app.config.globalProperties.$jquery = jquery;
app.use(store).use(router).use(ElementPlus).mount("#app");
// 以下为vue2的写法
import Vue from 'vue'
import ElementResizeDetectorMaker from "element-resize-detector";
import anime from "animejs";
import jquery from "jquery";
Vue.prototype.$erd = ElementResizeDetectorMaker();
Vue.prototype.$anime = anime;
Vue.prototype.$jquery = $jquery;
实现
在App.vue中书写以下代码:
<template>
<div id="app" :style="{ padding: pad }" class="hidden">
<div ref="appBox" class="app-box" :style="{ width: tw, height: th }">
<router-view />
</div>
</div>
</template>
<script>
export default {
data() {
return {
pad: "0",
w: 4160,
h: 1248,
fs: 30, //基本字体大小
tw: "100%",
th: "100%",
speed: 2,
ani: null,
};
},
created() {},
computed: {
mode() {
return this.$store.state.mode;
},
},
watch: {
mode() {
this.$jquery(this.$refs.appBox).css("transform", "none");
this.calc();
},
},
mounted() {
this.calc();
this.$nextTick(() => {
document.addEventListener("keydown", (e) => this.turnMode(e), true);
this.$erd.listenTo(document.querySelector("html"), () => {
this.$jquery(this.$refs.appBox).css("transform", "none");
this.calc();
});
this.$store.commit("addExW", this.$jquery(this.$refs.ex).outerWidth());
});
},
methods: {
calc: function () {
let fs = this.fs;
let html = document.querySelector("html");
let sc = this.w / this.h;
let ww = parseFloat(
document.defaultView.getComputedStyle(html, null).width
);
let wh = parseFloat(
document.defaultView.getComputedStyle(html, null).height
);
if (this.mode <= 2) {
let isEnough = this.h <= wh && this.w <= ww && this.mode == 2;
if (isEnough) {
this.pad = wh / 2 - this.h / 2 + "px " + (ww / 2 - this.w / 2) + "px";
} else {
if (sc < ww / wh) {
this.pad = "0 " + (ww / 2 - (wh * sc) / 2) + "px";
fs = (wh * fs) / this.h;
} else {
this.pad = wh / 2 - ww / sc / 2 + "px 0";
fs = (ww * fs) / this.w;
}
}
this.tw = "100%";
this.th = "100%";
this.$store.commit(
"addLeft",
isEnough
? ww / 2 - this.w / 2
: sc < ww / wh
? ww / 2 - (wh * sc) / 2
: 0
);
this.$store.commit(
"addTop",
isEnough
? wh / 2 - this.h / 2
: sc < ww / wh
? 0
: wh / 2 - ww / sc / 2
);
} else if (this.mode == 3) {
this.pad = "0";
if (sc < ww / wh) {
this.tw = ww + "px";
this.th = ww / sc + "px";
fs = (ww * fs) / this.w;
this.$nextTick(() => {
document.removeEventListener(
"keydown",
(e) => this.trans(e, 1),
true
);
document.addEventListener("keydown", (e) => this.trans(e, 1), true);
this.mouseWheel(
this.$refs.appBox,
() => this.trans({ keyCode: 38 }, 1, 240),
() => this.trans({ keyCode: 40 }, 1, 240)
);
});
} else {
this.tw = wh * sc + "px";
this.th = wh + "px";
fs = (wh * fs) / this.h;
this.$nextTick(() => {
document.removeEventListener(
"keydown",
(e) => this.trans(e, 0),
true
);
document.addEventListener("keydown", (e) => this.trans(e, 0), true);
this.mouseWheel(
this.$refs.appBox,
() => this.trans({ keyCode: 37 }, 0, 240),
() => this.trans({ keyCode: 39 }, 0, 240)
);
});
}
this.$store.commit("addLeft", 0);
this.$store.commit("addTop", 0);
} else if (this.mode == 4) {
this.pad = "0";
this.tw = "100%";
this.th = "100%";
fs = sc < ww / wh ? (wh * fs) / this.h : (ww * fs) / this.w;
this.$store.commit("addLeft", 0);
this.$store.commit("addTop", 0);
}
html.style["font-size"] = parseInt(fs) + "px";
this.$store.commit("increment", fs);
},
trans: function (e, s, st) {
let ts = s
? this.$jquery(this.$refs.appBox).outerHeight()
: this.$jquery(this.$refs.appBox).outerWidth();
let ws = s
? this.$jquery(this.$refs.appBox).parent().outerHeight()
: this.$jquery(this.$refs.appBox).parent().outerWidth();
let event = e || window.event;
let code = event.keyCode || event.which;
let of = parseFloat(
this.$jquery(this.$refs.appBox).css("transform")
? this.$jquery(this.$refs.appBox).css("transform").split(",")[
s ? 5 : 4
] || 0
: 0
);
let step = st || 120;
if (code == (s ? 38 : 37) && of < 0) {
let m = of + step > 0 ? 0 : of + step;
this.run(this.$refs.appBox, s, m - of);
} else if (code == (s ? 40 : 39) && ts + of - ws > 0) {
let m = ts + (of - step) - ws > 0 ? of - step : ws - ts;
this.run(this.$refs.appBox, s, m - of);
}
return false;
},
run: function (el, s, dis) {
this.$anime.remove(el);
this.ani = null;
let obj = {
targets: el,
duration: parseInt(Math.abs(dis) / this.speed),
easing: "linear",
};
if (s) {
obj.translateY = "+=" + dis;
} else {
obj.translateX = "+=" + dis;
}
this.ani = this.$anime(obj);
},
mouseWheel: function (ele, fn1, fn2) {
function wheelDelta(ev) {
// 使火狐浏览器 和标准浏览器的 滚轮数值返回一致
return ev.wheelDelta ? ev.wheelDelta : ev.detail * -40;
}
function clack(ev) {
if (wheelDelta(ev) < 0) {
fn2.call(ele);
} else {
fn1.call(ele);
}
}
if (navigator.userAgent.match(/Firefox/gi)) {
ele.addEventListener("DOMMouseScroll", function (ev) {
// 火狐浏览器
ev = ev || window.event;
ev.preventDefault();
clack(ev);
});
} else {
//其他浏览器 chrome ie
if (ele.addEventListener) {
ele.addEventListener(
"mousewheel",
function (ev) {
ev = ev || window.event;
ev.returnValue ? (ev.returnValue = false) : ev.preventDefault();
clack(ev);
},
{ passive: false }
);
} else {
ele.attachEvent("onmousewheel", function (ev) {
ev = ev || window.event;
if (ev.returnValue) {
ev.returnValue = false;
}
clack(ev);
});
}
}
},
turnMode: function (e) {
let event = e || window.event;
let code = event.keyCode || event.which;
let obj = {
49: 1,
50: 3,
};
let mode = obj[code] || this.mode;
this.$store.commit("exMode", mode);
},
exBtn: function () {
let mode = this.mode == 1 ? 3 : 1;
this.$store.commit("exMode", mode);
},
},
};
</script>
<style scoped>
.app-box {
box-sizing: border-box;
overflow: hidden;
background-size: 100% 100%;
user-select: none;
background-color: darkorange;
}
</style>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #fff;
background-color: #fff;
width: 100vw;
height: 100vh;
box-sizing: border-box;
font-size: 1rem;
}
</style>