大屏适配的本质:把设计稿的「逻辑像素」映射到「真实物理像素」,并在不同屏幕比例下决定「拉伸 / 留黑边 / 重排」三选一。
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>
或 vw:1px ≈ (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 Alternate、Bebas Neue、Oswald;中文搭配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,需要单独处理或让对方提供原生组件版本。
- 设计稿尺寸频繁变更:和设计师冷冻基准分辨率,否则每次返工。