大屏适配方案
- 方案一:rem 单位 + 动态设置 html 的 font-size;
- 方案二:vw 单位;
- 方案三:scale 等比例缩放
对比
方案一
核心思想:动态调整 HTML 根字体大小和 body 字体大小,结合百分比或vw/vh单位,实现容器宽高、字体大小、位移的动态适配。
优点:基于比例缩放,能够灵活适应不同分辨率和屏幕尺寸。
缺点:需要额外的计算和处理,可能增加开发复杂度。
方案二
核心思想:通过将像素值(px)转换为视口宽度(vw)和视口高度(vh)来适配不同尺寸的屏幕,实时计算图表尺寸、字体大小等。
优点:实时自适应不同屏幕大小,适合全屏应用。
缺点:在极端分辨率下可能出现不可预期的布局问题。
方案三
核心思想:根据屏幕宽高比例动态缩放,代码简洁,几行代码即可实现适配。
优点:实现简单,特别适合基本的大屏展示场景。
缺点:在地图、Canvas 等带有交互的组件中,可能会出现点击事件错位问题,需针对性调整。
方案1 – rem
- 动态设置HTML根字体大小 和 body 字体大小(lib_flexible.js)
- 将设计稿的宽(1920)平均分成 24 等份, 每一份为 80px。
- HTML字体大小就设置为 80 px,即1rem = 80px, 24rem = 1920px
- body字体大小设置为 16px。
- 安装 cssrem 插件, root font size 设置为 80px。
- 这个是px单位转rem的参考值 px 转 rem方式:手动 less/scss函数、cssrem插件、webpack插件、Vite插件
- 接着就可以按照 1920px * 1080px 的设计稿愉快开发,此时的页面已经是响应式,并且宽高比不变
lib_flexible.js
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (16 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 24
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
方案1 - rem
上面的方法是将页面等分并设置 1rem = 80px;
这个方案约定:将1920的基准字体大小设置为 14px,遇到其他尺寸自动按照与1920的比例对基准字体大小进行调整;并对 Echarts 进行处理;
useScreenAdapt.js
const FONT_SIZE = 14; // 基准字体大小
/**
* 计算相对的像素值
* @param {Number} size 像素值
* @returns {Number}
*/
export function transform(size) {
try {
const htmlSize = document.documentElement.style.fontSize.match(/\d+/)[0] || FONT_SIZE;
return (size * htmlSize) / FONT_SIZE;
} catch (error) {
return size;
}
}
/**
* 屏幕适配 hook
*/
export function useScreenAdapt() {
onMounted(() => {
let htmlContent = document.documentElement;
htmlContent.style.fontSize = `${(window.innerWidth / 1920) * FONT_SIZE}px`;
window.addEventListener("resize", () => {
htmlContent.style.fontSize = `${(window.innerWidth / 1920) * FONT_SIZE}px`;
});
});
}
大屏页面 index.vue
<!-- 大屏 -->
<template>
<div class="container">
<headerDate />
<leftPanel />
<Map />
<rightPanel />
</div>
</template>
<script setup>
import leftPanel from "./components/leftPanel/index.vue";
import Map from "./components/jinjitan/index.vue";
import rightPanel from "./components/rightPanel/index.vue";
import headerDate from "./components/header/index.vue";
import { useScreenAdapt } from "./hooks/useScreenAdapt";
useScreenAdapt();
</script>
<style lang="scss" scoped>
.container {
width: 100vw;
height: 100vh;
background: #333;
position: relative;
}
</style>
样式使用 rem
对于 Echarts ,使用 transform 方法设置字体大小
参数:传入在1980屏幕下对应的字号大小
方案2 - vw
- 屏幕的宽默认为 100vw,那么100vw = 1920px, 1vw = 19.2px 。
- 安装 cssrem 插件, body的宽高(1920px * 1080px)直接把px单位转vw单位
- px 转 vw 方式:手动、less/scss函数、cssrem插件、webpack插件、Vite插件
- 接着就可以按照 1920px * 1080px 的设计稿愉快开发,此时的页面已经是响应式,并宽高比不变。
方案3 - scale
使用CSS3中的scale函数来缩放网页,这里我们将使用两种方案来实现:
- 方案一:直接根据宽度的比率进行缩放。(宽度比率=网页当前宽 / 设计稿宽)
- 方案二:动态计算网页宽高比,决定是是否按照宽度的比率进行缩放。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body, ul{
margin: 0;
padding: 0;
}
body{
width: 1920px;
height: 1080px;
box-sizing: border-box;
border: 3px solid red;
/* 指定缩放的原点在左上角 */
transform-origin: left top;
}
ul{
width: 100%;
height: 100%;
list-style: none;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
li{
width: 33.333%;
height: 50%;
box-sizing: border-box;
border: 2px solid green;
font-size: 30px;
}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script>
// 设计稿: 1920 * 1080
// 目标适配: 1920 * 1080 3840 * 2160 ( 2 * 2 ) ; 7680 * 2160( 4 * 2)
// 1.设计稿的尺寸
let targetX = 1920
// 2.拿到当前设备(浏览器)的宽度
let currentX = document.documentElement.clientWidth || document.body.clientWidth
// 1920 * 1080 -> 3840 * 2160
// 3.计算缩放比例
let scaleRatio = currentX / targetX; // 参照宽度进行缩放
// 4.开始缩放网页
document.body.style = `transform: scale(${scaleRatio})`
</script>
</body>
</html>
完美适配 3840 * 2160
此时有个问题出现了
- 在7680*2160的屏幕下,出现了超出屏幕高度,出现了滚动条
- 为什么会出现这个问题
- 因为我们使用scale进行缩放的时候 放大了四倍 1920x4= 7680 1080 x 4= 4320
- 这个时候很明显1080高度无法放下4320高度所以出现了滚动条
- 如何解决
- 这个时候我们不能参照宽度进行缩放( 默认情况 )
- 需要判断如果视口宽高比大于设计稿宽高比就参照高度进行缩放
- 比如 3840 / 2160 > 1920 / 1080 就按照参照高度进行缩放 -js代码更改
// 设计稿: 1920 * 1080
// 目标适配: 1920 * 1080 3840 * 2160 ( 2 * 2 ) ; 7680 * 2160( 4 * 2)
// 1.设计稿的尺寸
let targetX = 1920;
let targetY = 1080;
let oldRatio = targetX / targetY;
// 2.拿到当前设备(浏览器)的宽度
let currentX =
document.documentElement.clientWidth || document.body.clientWidth;
let currentY =
document.documentElement.clientHeight || document.body.clientHeight;
// 1920 * 1080 -> 3840 * 2160
// 3.计算缩放比例
let scaleRatio = currentX / targetX; // 参照宽度进行缩放 ( 默认情况 )
let currentRatio = currentX / currentY; // 宽高比率
// 超宽屏
if (currentRatio > oldRatio) {
scaleRatio = currentY / targetY; // 参照高度进行缩放
document.body.style = `width:${targetX}px; height:${targetY}px;transform: scale(${scaleRatio}) translateX(-50%); left: 50%`;
} else {
// 4.开始缩放网页
document.body.style = `width:${targetX}px; height:${targetY}px; transform: scale(${s caleRatio})`;
}
https://juejin.cn/post/7254200330493444151