基于现目前所做数据可视化项目的不同分辨率兼容需求总结以下适配几种方案供参考。
开发过程中根据设计图标注的数值进行开发,借助
postcss-pxtorem
设置root
的font-size
和自动将px
转化为rem
<template>
<div ref="remRef" :style="{ width: widthRem, height: heightRem }">
<slot>slot>
div>
template>
<script lang="ts" setup name="BigScreenRem">
import { computed, onMounted, ref } from 'vue'
import _ from 'lodash'
type Props = {
width?: number
height?: number
rootValue?: number
}
const props = withDefaults(defineProps<Props>(), {
width: 1920,
height: 1080,
rootValue: 192
})
const remRef = ref()
const fontSize = ref(192)
const widthRem = computed(() => {
return (Number.parseFloat(props.width.toString()) / props.rootValue).toFixed(5) + 'rem'
})
const heightRem = computed(() => {
return (Number.parseFloat(props.height.toString()) / props.rootValue).toFixed(5) + 'rem'
})
const reRender = () => {
const docEl: HTMLElement = document.documentElement
const screenWidth: number = docEl.clientWidth
const screenHeight: number = docEl.clientHeight
if (!screenWidth || !screenHeight) return
const screenRatio: number = screenWidth / screenHeight
const screenRatioDesign: number = props.width / props.height
if (screenRatio > screenRatioDesign) {
// screenRatio > screenRatioDesign 说明屏幕比较宽 则 高度撑满 左右居中
// console.log('screenRatio > screenRatioDesign 说明屏幕比较宽 则 高度撑满 左右居中')
// 这边之所以 * screenRatioDesign 是因为 postcss 默认的 rootValue 是 1920 / 10
// 用高度计算 fontSize 则需要把之前的关系乘上去
fontSize.value = (screenHeight / 10) * screenRatioDesign
} else if (screenRatio < screenRatioDesign) {
// screenRatio < screenRatioDesign 说明屏幕比较长 则宽度撑满 上下居中
// console.log('screenRatio < screenRatioDesign 说明屏幕比较长 则宽度撑满 上下居中')
fontSize.value = screenWidth / 10
} else {
fontSize.value = screenWidth / 10
}
document.documentElement.style.fontSize = fontSize.value.toFixed(5) + 'px'
}
onMounted(() => {
reRender()
window.addEventListener('resize', _.debounce(reRender, 500), false)
document.addEventListener('DOMContentLoaded', _.debounce(reRender, 500), false)
})
script>
开发过程中根据设计图标注的数值进行开发,通过计算实际的宽高比与设计稿的宽高比,从而进行缩放
<template>
<div ref="scaleRef" :style="{ width: width + 'px', height: height + 'px' }">
<slot>slot>
div>
template>
<script lang="ts" setup name="BigScreenScale">
import { onMounted, ref } from 'vue'
import _ from 'lodash'
type Props = {
width?: number
height?: number
rootValue?: number
}
const props = withDefaults(defineProps<Props>(), {
width: 1920,
height: 1080,
rootValue: 192
})
const scaleRef = ref()
const reRender = () => {
const docEl: HTMLElement = document.documentElement
const screenWidth: number = docEl.clientWidth
const screenHeight: number = docEl.clientHeight
if (!screenWidth || !screenHeight) return
const widthScale = (screenWidth / props.width).toFixed(10)
const heightScale = (screenHeight / props.height).toFixed(10)
const scale = widthScale < heightScale ? widthScale : heightScale
document.documentElement.style.fontSize = props.rootValue + 'px'
scaleRef.value.style.transform = `scale(${scale})`
scaleRef.value.style.transformOrigin = 'left top'
console.log(props.width * Number(scale))
console.log(props.height * Number(scale))
if (widthScale > heightScale) {
scaleRef.value.style.marginLeft = (screenWidth - Number.parseInt((props.width * Number(scale)).toFixed(2))) / 2 + 'px'
} else {
scaleRef.value.style.marginTop = (screenHeight - Number.parseInt((props.height * Number(scale)).toFixed(2))) / 2 + 'px'
}
scaleRef.value.style.marginLeft = (screenWidth - Number.parseInt((props.width * Number(scale)).toFixed(2))) / 2 + 'px'
}
onMounted(() => {
reRender()
window.addEventListener('resize', _.debounce(reRender, 500), false)
document.addEventListener('DOMContentLoaded', _.debounce(reRender, 500), false)
})
script>
开发过程中根据设计图标注的数值进行开发,通过计算实际的宽高比与设计稿的宽高比,设置
zoom
的大小。
<template>
<div ref="zoomRef" :style="{ width: width + 'px', height: height + 'px' }">
<slot>slot>
div>
template>
<script lang="ts" setup name="BigScreenZoom">
import { nextTick, onMounted, ref } from 'vue'
import _ from 'lodash'
type Props = {
width?: number
height?: number
rootValue?: number
}
const props = withDefaults(defineProps<Props>(), {
width: 1920,
height: 1080,
rootValue: 192
})
const zoomRef = ref()
const reRender = () => {
const docEl: HTMLElement = document.documentElement
const screenWidth: number = docEl.clientWidth
const screenHeight: number = docEl.clientHeight
if (!screenWidth || !screenHeight) return
const widthScale = (screenWidth / props.width).toFixed(10)
const heightScale = (screenHeight / props.height).toFixed(10)
console.log(widthScale, heightScale)
const scale = widthScale < heightScale ? widthScale : heightScale
document.documentElement.style.fontSize = props.rootValue + 'px'
nextTick(() => {
zoomRef.value.style.zoom = scale
})
}
onMounted(() => {
reRender()
window.addEventListener('resize', _.debounce(reRender, 500), false)
document.addEventListener('DOMContentLoaded', _.debounce(reRender, 500), false)
})
script>
scale
进行缩小缩放时候,虽然内容缩小了,但是占用的空间却没有变化。这也就是为什么1920 * 1080 在 1280 * 720 上的显示效果
和 1920 * 1080 在 1366 * 768 上的显示效果
下方有一块黑色区块的原因zoom
最初仅在 Internet Explorer
中实现。尽管其他一些浏览器也支持该属性,但推荐使用transform: scale()
来缩放内容。transform: scale()
与 zoom
的工作方式不同。例如,如果在 html
或 body
元素上使用transform: scale(0.6)
,那么它会调整整个页面的大小,显示一个缩小的页面,周围有巨大的白色边距,而 zoom: 0.6
缩放页面上的元素,但不缩放绘制元素的页面本身。