数据大屏常用布局-等比缩放布局(Scale Laylout)-使用 CSS Transform Scale 实现等比缩放

数据大屏常用布局-等比缩放布局(Scale Laylout)-使用 CSS Transform Scale 实现等比缩放

1.介绍

1.1 典型特征和典型特点

Scale Layout 的典型特征:

1.浏览器缩小

2.整个页面一起缩

3.布局不变

4.字体可以缩到几 px

工程上意味着:

  • 页面有一个固定"设计尺寸"
  • 浏览器变化时 不重排(不 reflow)
  • 只是 整体做 transform

为什么适合数据大屏?

数据大屏的典型特点

  • 固定分辨率设计(1920×1080 / 3840×2160)
  • 主要是 看,不是 点
  • 运行环境可控(会议室 / 大屏电视)

1.2 效果展示

效果实现展示:

1.3 CSS 编写原则

在这种方案下,你的 CSS 编写原则是

CSS 世界里永远是 1920×1080,缩放交给 JS,使用固定 px,不要写响应式

2.实战案例-使用 CSS Transform Scale 实现等比缩放

  1. 固定设计尺寸

在全局样式中,#app 被设置为固定的设计尺寸:

Index.css

css 复制代码
#app {
  @apply inline-block absolute left-1/2;
  width: 1920px;
  height: 1080px;
  transform-origin: 0 0;
  color: rgba(255, 255, 255, 0.9);
}
  1. 动态缩放计算

使用 useScreenScale hook 计算缩放比例:

typescript 复制代码
import { onMounted, onUnmounted } from 'vue'

const useScreenScale = () => {
	/**
	 * Scales the screen based on the design dimensions.
	 * window resize is not usually triggered, so no need to use debounce
	 * @return {void} This function does not return a value.
	 */
	const handleScreenScale = () => {
		const designDreftWidth = 1920
		const designDreftHeight = 1080

		const scale =
			document.documentElement.clientWidth / document.documentElement.clientHeight <
			designDreftWidth / designDreftHeight
				? document.documentElement.clientWidth / designDreftWidth
				: document.documentElement.clientHeight / designDreftHeight

		if (document.querySelector('#app') !== null) {
			;(document.querySelector('#app') as HTMLElement).style.transform =
				`scale(${scale}) translate(-50%)`
		}
	}
	onMounted(() => {
		handleScreenScale()
		window.onresize = () => handleScreenScale()
	})

	onUnmounted(() => {
		window.onresize = null
	})
}

export default useScreenScale

缩放逻辑:

  • 比较当前屏幕宽高比与设计稿宽高比(16:9)

  • 如果屏幕更窄:按宽度缩放 scale = 屏幕宽度 / 1920

  • 如果屏幕更高:按高度缩放 scale = 屏幕高度 / 1080

  • 应用变换:transform: scale(scale) translate(-50%)

    • translate(-50%)和left(50%)配合,实现水平居中
  • scale() 缩放,scale就是缩放比例

  • translate(-50%) 配合 left-1/2 实现居中

  1. 在 App.vue 中启用
javascript 复制代码
<script setup lang="ts">
useScreenScale()
</script>

页面如何实现等比缩放?

页面无需额外处理,因为:

所有页面都在 #app 内部

#app 整体缩放,内部元素自动跟随

使用固定像素值即可,例如:

html 复制代码
 <div class="w-[1114px] h-full">
        <HistoryEventsList
          ref="historyEventsListRef"
          @update:queryParams="handleTrendQuery"
          @open:warningEventDetail="handleOpenWarningEventDetail"
        />
      </div>
      <div class="w-[738px] h-full">

这些固定像素值(如 1114px、738px)会随 #app 的缩放比例自动缩放。

3.注意坑点- Element Plus 弹出层的默认行为

Element Plus 弹出层的默认行为,Element Plus 的弹出层组件(el-select、el-cascader、el-date-picker 等)默认会将下拉菜单挂载到 body 上,而不是组件所在的 DOM 树中。

DOM 结构示意:

html 复制代码
<body>
  <div id="app">  ← 这里应用了 transform: scale(0.75)
    <HistoryEventsList>
      <el-select>  ← 输入框在这里
      </el-select>
    </HistoryEventsList>
  </div>
  
  <!-- 默认情况下,下拉菜单会挂载到这里 -->
  <div class="el-select-dropdown">  ← 下拉菜单在 body 下,不在 #app 内!
    <el-option>...</el-option>
  </div>
</body>

由于缩放是写在app上的,但是弹出层挂在了body上,所以应该将弹出层挂到app上,使用append-to="#app"

html 复制代码
<el-date-picker
            v-model="currentDateRange"
            :shortcuts="EVENT_SHORTCUTS"
            append-to="#app"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            size="small"
            :style="{ width: '100%', height: '32px' }"
          />
相关推荐
犬大犬小7 小时前
从头说下DOM XSS
前端·javascript·xss
绿鸳7 小时前
Socket.IO实时通信
前端
Cache技术分享7 小时前
273. Java Stream API - Stream 中的中间操作:Mapping 操作详解
前端·后端
我的div丢了肿么办7 小时前
echarts中appendData的详细讲解
前端·javascript·vue.js
JamesGosling6667 小时前
async/defer 执行顺序全解析:从面试坑到 MDN 标准
前端·javascript
喝咖啡的女孩7 小时前
Web Worker 前端多线程解析
前端
一水鉴天7 小时前
整体设计 定稿 之6 完整设计文档讨论及定稿 之3 整体设计原则(原型-过程-模块三阶联动体系)
前端·数据库·人工智能
静待雨落7 小时前
zustand持久化
前端·react.js