CSS 单位方案
1 使用 vw/vh 单位
/* 基于设计稿1920*1080 */
.container {
width: calc(100vw - 40px);
height: calc(100vh - 60px);
}
.card {
width: 25vw; /* 占视口宽度25% */
height: 30vh; /* 占视口高度30% */
font-size: calc(12px + 0.5vw); /* 字体响应式 */
}
2 rem 方案(推荐)
// 设置基准 rem
function setRem() {
const baseSize = 16; // 基础字体大小
const designWidth = 1920; // 设计稿宽度
const scale = document.documentElement.clientWidth / designWidth;
document.documentElement.style.fontSize =
baseSize * Math.min(scale, 2) + 'px'; // 限制最大缩放
}
window.addEventListener('resize', setRem);
setRem();
缩放方案
1 transform: scale 缩放
class ScreenAdapter {
constructor(options = {}) {
this.options = {
designWidth: 1920,
designHeight: 1080,
...options
};
this.init();
}
init() {
this.updateScale();
window.addEventListener('resize', () => this.updateScale());
}
updateScale() {
const { clientWidth, clientHeight } = document.documentElement;
const { designWidth, designHeight } = this.options;
// 计算缩放比例
const scaleX = clientWidth / designWidth;
const scaleY = clientHeight / designHeight;
const scale = Math.min(scaleX, scaleY); // 取最小比例保持比例
// 应用缩放
const app = document.getElementById('app');
if (app) {
app.style.transform = `scale(${scale})`;
app.style.transformOrigin = 'top left';
app.style.width = `${designWidth}px`;
app.style.height = `${designHeight}px`;
}
}
}
媒体查询方案
/* 超宽屏(>2560px) */
@media screen and (min-width: 2560px) {
.chart-container {
padding: 2rem;
}
.card {
margin: 1.5rem;
}
}
/* 标准屏(1920px) */
@media screen and (min-width: 1920px) and (max-width: 2559px) {
.chart-container {
padding: 1rem;
}
}
/* 笔记本屏(1366px) */
@media screen and (max-width: 1919px) {
.grid-container {
grid-template-columns: repeat(2, 1fr);
}
.font-size {
font-size: 0.9rem;
}
}
/* 高度适配 */
@media screen and (max-height: 800px) {
.header {
height: 50px;
}
.content {
height: calc(100vh - 50px);
}
}
Flexible + 网格布局
/* 使用 CSS Grid 创建响应式布局 */
.dashboard {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 20px;
padding: 20px;
}
/* 使用 Flexbox */
.chart-row {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.chart-item {
flex: 1 1 calc(33.333% - 20px);
min-width: 300px;
margin: 10px;
}
图表库适配
1 ECharts 适配
const initChart = () => {
const chart = echarts.init(dom);
const resizeChart = () => {
chart.resize();
};
// 使用防抖
const debounceResize = _.debounce(resizeChart, 300);
window.addEventListener('resize', debounceResize);
// 响应式配置
chart.setOption({
grid: {
left: '3%',
right: '4%',
bottom: '10%',
top: '10%',
containLabel: true
},
textStyle: {
fontSize: window.innerWidth < 1920 ? 12 : 14
}
});
};
2 AntV G2/G6 适配
class GraphAdapter {
constructor(graph) {
this.graph = graph;
this.initResizeListener();
}
initResizeListener() {
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
const { width, height } = entry.contentRect;
this.graph.changeSize(width, height);
}
});
observer.observe(this.graph.container);
}
}
完整适配方案示例
// 大屏适配管理器
class ScreenAdapter {
constructor() {
this.designWidth = 1920;
this.designHeight = 1080;
this.currentMode = 'scale';
this.init();
}
init() {
this.setRem();
this.bindEvents();
this.adaptCharts();
}
// 方案1: REM适配
setRem() {
const width = document.documentElement.clientWidth;
const height = document.documentElement.clientHeight;
// 计算比例
const scaleX = width / this.designWidth;
const scaleY = height / this.designHeight;
const scale = Math.min(scaleX, scaleY);
// 设置根字体大小
document.documentElement.style.fontSize =
`${16 * scale}px`;
}
// 方案2: Scale适配
scaleAdapt() {
const app = document.getElementById('app');
if (!app) return;
const { clientWidth, clientHeight } = document.documentElement;
const scaleX = clientWidth / this.designWidth;
const scaleY = clientHeight / this.designHeight;
const scale = Math.min(scaleX, scaleY);
app.style.transform = `scale(${scale})`;
app.style.transformOrigin = '0 0';
app.style.width = `${this.designWidth}px`;
app.style.height = `${this.designHeight}px`;
}
// 绑定事件
bindEvents() {
const debounceAdapt = _.debounce(() => {
this.setRem();
this.adaptCharts();
}, 300);
window.addEventListener('resize', debounceAdapt);
window.addEventListener('orientationchange', debounceAdapt);
}
// 适配图表
adaptCharts() {
// 获取所有图表实例并重新渲染
document.querySelectorAll('[data-chart]').forEach(chartDom => {
const chart = echarts.getInstanceByDom(chartDom);
if (chart) {
chart.resize();
}
});
}
// 切换适配模式
switchMode(mode) {
this.currentMode = mode;
if (mode === 'scale') {
this.scaleAdapt();
} else {
this.setRem();
}
}
}
// 使用
const adapter = new ScreenAdapter();
注意事项
-
性能优化:

- 使用防抖/节流避免频繁重绘
- 使用 CSS will-change 属性优化
- 合理使用硬件加速
-
字体适配:
/* 使用 clamp() 函数 */{ font-size: clamp(16px, 1.5vw, 24px); } -
图片适配:
<!-- 使用 picture 标签 --> <picture> <source media="(min-width: 1920px)" srcset="large.jpg"> <source media="(min-width: 1366px)" srcset="medium.jpg"> <img src="small.jpg" alt="..."> </picture>
-
浏览器兼容性:
- 添加必要的 polyfill
- 测试不同浏览器表现
推荐方案组合
对于 openclaw 这类数据可视化大屏,建议:
主方案:rem + vw/vh 单位
备用方案:transform: scale 缩放
配合:CSS Grid/Flexbox 布局
图表:ECharts/AntV 内置适配
这样既能保证适配效果,又能提供良好的用户体验。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。