适配组件-RootContainer
该组件会根据当前配置(如全屏模式、自动拉伸等)调整根元素和子容器的样式。包括位置、大小以及缩放比例。主要用于响应式布局或全屏适配场景。
使用
应用页面
<template>
<RootContainer>
<!-- your components here -->
</RootContainer>
</template>
<style>
.root-container {
position: absolute;
left: 0px;
top: 0px;
bottom: 0px;
right: 0px;
border: 0px !important;
padding: 0px !important;
margin: 0px !important;
}
.view-context-container {
position: absolute;
transform-origin: top left;
overflow: hidden;
border: 0px !important;
padding: 0px !important;
margin: 0px !important;
}
</style>
RootContainer.vue
<template>
<div ref="rootElement" class="root-container">
<div ref="subContainer" class="view-context-container">
<slot></slot>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from "vue";
const props = defineProps({
width: { type: Number, default: 0 },
height: { type: Number, default: 0 },
isFull: { type: Boolean, default: false },
fullScreen: { type: Boolean, default: true },
autoStretch: { type: Boolean, default: true },
autoDescale: { type: Boolean, default: false }
});
const emit = defineEmits(['scales',])
const rootElement=ref(null)
const subContainer=ref(null)
watch(autoStretch,()=>{
redraw()
})
watch(width,()=>{
redraw()
})
watch(height,()=>{
redraw()
})
watch(fullScreen,()=>{
redraw()
})
watch(isFull,()=>{
redraw()
})
function redraw(){
if (!rootElement.value) return
rootElement.value.style.position = props.fullScreen ? 'fixed' : 'absolute'
//实际内容宽高screen.availWidth,screen.availHeight
let width = props.width || (props.fullScreen ? screen.availWidth : rootElement.value.offsetWidth)
let height = props.height || (props.fullScreen ? screen.availHeight : rootElement.value.offsetHeight)
let w = props.fullScreen ? window.innerWidth : rootElement.value.offsetWidth,
h = props.fullScreen ? window.innerHeight : rootElement.value.offsetHeight
let rateW = w / width,
rateH = h / height
let rate = Math.min(rateW, rateH)
let el = subContainer.value
if (el) {
let elW = rate < 1 || props.autoStretch ? width * rate : width,
elH = rate < 1 || props.autoStretch ? height * rate : height
el.style.width = width + 'px'
el.style.height = height + 'px'
if (rate < 1 || props.autoStretch) {
if (props.isFull) {
el.style.transform = `scale(${rateW}, ${rateH})`;
emit('scales', w,height,rateW, rateH)
}else{
el.style.transform = 'scale(' + rate + ')'
emit('scales', rate, rate)
}
traceScale({scale: rate,})
}else{
el.style.transform = ''
traceScale({scale: 1,})
}
if (!props.isFull) {
el.style.left = (w - elW) / 2 + 'px'
el.style.top = (h - elH) / 2 + 'px'
}
}
}
function traceScale(s) {
emit('scale', s);
if (props.autoDescale) {
const forEachChild = o => {
if (o.descale && typeof o.descale === 'function') {
o.descale(s.scale)
return;
} else if (o.$children) {
o.$children.forEach(forEachChild)
}
}
this.$children.forEach(forEachChild)
}
}
onMounted(()=>{
let bindedMethod = () => {
redraw()
}
redraw()
//window.addEventListener('resize', bindedMethod)
])
</script>
<style>
.root-container {
position: absolute;
left: 0px;
top: 0px;
bottom: 0px;
right: 0px;
border: 0px !important;
padding: 0px !important;
margin: 0px !important;
}
.view-context-container {
position: absolute;
transform-origin: top left;
overflow: hidden;
border: 0px !important;
padding: 0px !important;
margin: 0px !important;
}
</style>
属性
| 属性 | 默认 | 说明 |
|---|---|---|
| fullScreen | true | 是否按全屏模式自动适配,默认为是,是则表示容器目标为全屏的 window,否则表示容器目标为此组件的父级 dom |
| width | -- | 设计的高度,默认为运行环境屏幕的高度或父级 dom 的内高 |
| height | -- | 设计的高度,默认为运行环境屏幕的高度或父级 dom 的内高 |
| autoStrech | true | 当设计高宽小于容器目标高宽时,是否自动拉伸到 |
| isFull | false | 是否按比例让内容铺满 |
效果图
铺满整个屏幕。
留白边。
修改屏幕比例后。
autofit.js
这款自实用工具使用简单,并且会让页面内容始终占满整个屏幕,不留空白。
注意:当设置宽高度单位为 vw、vh 时可能会出现留白问题,在使用过程中应尽量避免使用该单位
npm安装
npm i autofit.js
应用页面
import autofit from "autofit.js";
import { onMounted, onBeforeUnmount } from "vue";
onMounted(() => {
autofit.init({
dh: 1080,
dw: 1920,
el: ".moduleNavigation",//自适应页面
resize: true
})
});
onBeforeUnmount(() => {
autofit.off()
})