04 · 分辨率与适配方案

0 阅读4分钟

大屏适配的本质:把设计稿的「逻辑像素」映射到「真实物理像素」,并在不同屏幕比例下决定「拉伸 / 留黑边 / 重排」三选一。

1. 三种主流方案

方案原理优点缺点
A. CSS transform: scale整屏按比例缩放,DOM 尺寸不变一次写死、最省事比例不一致时变形或留黑边;事件坐标需校正
B. rem / vw 换算字体、间距按视口比例算文本细腻、不变形Canvas/SVG 内部尺寸需另算
C. 响应式重排(栅格)不同分辨率下重排组件多端通用大屏视觉控不住,复杂度高

领导汇报、监控大屏:默认 A(scale)多分辨率响应式大屏:用 B 或 A + B 混合拼接屏 + 单源信号:通常硬件控制器已处理,前端只输出基准分辨率,仍走 A

2. 方案 A:transform scale 经典实现

2.1 原理图

┌──────── 物理屏 (例如 3840×1080) ─────────┐
  ┌──── 设计稿 1920×1080,scale=2 ─────┐  
          占满物理 3840×1080           
  └─────────────────────────────────────┘  
└──────────────────────────────────────────┘

2.2 计算逻辑

function getScale(designW: number, designH: number) {
  const sw = window.innerWidth  / designW;
  const sh = window.innerHeight / designH;
  // 三种策略:
  // - 'fit'    : Math.min(sw, sh) → 留黑边,不变形(推荐汇报型)
  // - 'fill'   : Math.max(sw, sh) → 满屏,可能裁剪
  // - 'stretch': { sx: sw, sy: sh } → 拉伸变形(比例差异大时不要用)
  return Math.min(sw, sh);
}

function applyScale() {
  const k = getScale(1920, 1080);
  const root = document.querySelector<HTMLElement>('#stage')!;
  root.style.width  = '1920px';
  root.style.height = '1080px';
  root.style.transform = `scale(${k})`;
  root.style.transformOrigin = 'left top';
  // 居中:
  root.style.left = (window.innerWidth  - 1920 * k) / 2 + 'px';
  root.style.top  = (window.innerHeight - 1080 * k) / 2 + 'px';
}

window.addEventListener('resize', applyScale);
applyScale();

2.3 注意事项

  • 整屏所有元素都按 1920×1080 设计稿写 px;不要混用 vw/vh。
  • 输入框、坐标拾取要除以 k 还原真实坐标;ECharts 内部已处理。
  • transform 会触发 GPU 合成,注意子元素若用 position: fixed 会失效——大屏里禁用 fixed
  • 字体小到 12px 以下时,scale 会糊;统一最小字号 14px。

3. 方案 B:rem / vw 实现

<!-- 1920 设计稿,1px = 1/192 rem,根字号 100px 时 1rem = 100px -->
<script>
  function setRem() {
    document.documentElement.style.fontSize =
      (window.innerWidth / 19.2) + 'px';   // 1rem = (innerWidth/1920)*100
  }
  window.addEventListener('resize', setRem);
  setRem();
</script>

vw1px ≈ (1/19.2) vw = 0.05208vw。Sass / postcss-pxtorem 自动转换:

.kpi { font-size: pxToRem(36); height: pxToRem(120); }

适用:图表内部要保持「文字相对清晰」、布局要按屏幕等比放大。ECharts 此时要监听 resize 自动 chart.resize()

4. 方案 C:响应式栅格

适合 BI 自助看板:

  • react-grid-layout / gridstack 提供拖拽 + 响应式断点。
  • 定义断点:{ xl: 1920, lg: 1440, md: 1024, sm: 768 }
  • 每个断点存一份布局;用户拖完保存到 schema。

不要用响应式做汇报型大屏:领导永远只看 1920×1080 那一稿,重排了反而不像「成品」。

5. 拼接屏的几种现实情况

5.1 单信号源 + 控制器拼接(最常见)

浏览器 1 路 1920×1080 信号 ──→ 拼接屏控制器 ──→ N 块物理屏
                                 (画面切割/拉伸)

前端只需输出 1920×1080 或 3840×2160,适配按方案 A 即可,跟单屏没区别。

5.2 多信号源 + 一屏一信号

每块物理屏独立一台显卡输出:

  • 选项 1:每块屏单独跑一份大屏页面,URL 带 ?screen=1 参数加载该屏的 schema 子集。
  • 选项 2:一台主机多显示器 + Electron 多窗口(详见 09)。

5.3 整体超宽分辨率(如 7680×1920)

// 设计稿就按 7680×1920 出
applyScaleFor({ designW: 7680, designH: 1920 });
  • ECharts 这种内部使用真实像素的库,自动跟着尺寸走。
  • WebGL(Three.js/Cesium)注意 setPixelRatio:高分屏 dpr=2 时,7680×1920 实际渲染 15360×3840,显卡吃不消,需要把 dpr 限在 1.0~1.25。

6. DPR(Device Pixel Ratio)处理

  • window.devicePixelRatio 在 4K/5K 屏会到 2 甚至 3,WebGL 默认会按 dpr 渲染,性能压力翻倍。
  • 大屏建议 统一锁定 dpr=1(牺牲一点细腻度,换稳定帧率):
    renderer.setPixelRatio(1);   // Three.js
    
  • 2D Canvas 仍按 dpr 缩放,否则模糊。

7. 字体与可读性

  • 远距离阅读:核心数字 ≥ 64px,标题 ≥ 32px,正文 ≥ 18px(按 1920 设计稿)。
  • 数字字体推荐:DIN AlternateBebas NeueOswald;中文搭配 PingFang SC / 思源黑体
  • 字重不要全用 Light,远看会糊;标题用 Medium/Bold,正文 Regular。

8. 适配 checklist

  • 设计稿基准分辨率写进 schema,不出现魔法数字。
  • 不同物理分辨率下 fit/fill/stretch 策略已确认(最好走 fit + 黑边或自适应背景)。
  • ECharts/SVG/3D 都会响应窗口 resize。
  • 演示前用真实大屏分辨率(或 chrome devtools 模拟)走一遍。
  • 拼接屏方案与硬件方对齐:是控制器拼接还是多信号源?

9. 反模式

  • 整屏 100vw / 100vh + 固定 px 混用:缩放后必错位。
  • 要在大屏里嵌 iframe 别人的页面:iframe 不会跟着 transform scale,需要单独处理或让对方提供原生组件版本。
  • 设计稿尺寸频繁变更:和设计师冷冻基准分辨率,否则每次返工。