Files
tianshu-engine/docs/guide/UI_SCALING.md

2.5 KiB
Raw Blame History

UI 屏幕适配方案

原则

不做响应式布局,只做等比缩放。 天书的 UI 是为 1920×1080 画布设计的,所有屏幕统一等比缩放,不发散断点。

实施方案:transform: scale()

入口处加 3 行

<!-- index.html / editor/index.html -->
<style>
  html, body {
    width: 100vw; height: 100vh; overflow: hidden;
  }
  #app {
    width: 1920px; height: 1080px;
    transform-origin: top left;
    transform: scale(var(--scale));
  }
</style>
// main.ts — app mount 前
const scale = Math.min(window.innerWidth / 1920, window.innerHeight / 1080)
document.documentElement.style.setProperty('--scale', String(scale))

// resize 时更新
window.addEventListener('resize', () => {
  const s = Math.min(window.innerWidth / 1920, window.innerHeight / 1080)
  document.documentElement.style.setProperty('--scale', String(s))
})

影响范围

影响的 说明
所有 px 等比缩放,按钮/字号/间距全部生效
SVG / Canvas 内部坐标 天然缩放,无需换算
⚠️ position: fixed transformnone 的元素会创建新的坐标基准,fixed 定位可能"粘"在缩放容器内而非视口。解决: overlay 统一用 position: absolute,根容器设 position: relative

兼容注意事项

属性 兼容性
backdrop-filter Chromium bug: transform 父容器内可能失效。把 backdrop-filter 放到 transform 容器外面(比如直接在 body 上)
getBoundingClientRect() 返回的是缩放前的逻辑坐标,需 ÷ scale 得到实际屏幕坐标
window.innerWidth/Height 始终返回物理像素,用于计算 scale内部逻辑坐标始终 = 设计尺寸

为什么不用 rem / clamp / media query

  • 无断点布局需求 — 不是手机→平板→桌面三套排版,只是等比缩放一张画布
  • 改动量rem 需要把 200+ 处 px 改为 rem,收益为零
  • 创作者 — 后续页面新增不需要考虑响应式,直接按 1920×1080 画布设计

新增页面的适配清单

当需要新增一个全屏页面(如新弹窗/面板)时:

  • 所有尺寸使用 px(不要用 vw/vh/rem
  • 弹窗用 position: absolute(不用 fixed
  • 弹窗的父容器设 position: relative
  • backdrop-filter 时,确认它在非 transform 的父容器内
  • 设计画布按 1920×1080 基准