数据大屏常用布局-等比缩放布局(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' }"
          />
相关推荐
一袋米扛几楼989 分钟前
【Git】规范化协作:详解 GitHub 工作流中的 Issue、Branch 与 Pull Request 最佳实践
前端·git·github·issue
网络点点滴22 分钟前
前端与后端的区别与联系
前端
EnCi Zheng1 小时前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen1 小时前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技1 小时前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人1 小时前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实1 小时前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha1 小时前
三目运算符
linux·服务器·前端
晓晨的博客1 小时前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript