图表用vw/vh会失真,因canvas未重绘、devicePixelRatio未适配、宽高比未解耦;需ResizeObserver监听+显式resize()+初始化传devicePixelRatio。

直接用 vw/vh 设容器宽高,图表必失真——因为 canvas 没重绘、devicePixelRatio 没适配、比例没解耦。
为什么 width: 80vw + height: 50vh 会让 Chart.js/ECharts 变糊变歪?
视口单位只改了容器 CSS 尺寸,但图表库初始化时已按当前像素值创建 canvas 缓冲区。缩放后:canvas 像素密度没变,devicePixelRatio 被忽略,文字锯齿、坐标偏移、图例截断全来了。
- Chart.js 默认 canvas 是 600×400 像素,哪怕容器缩到 300×200,它仍用原分辨率渲染,再被 CSS 拉伸
- ECharts 的
setOption不自动响应容器尺寸变化,必须显式调resize() - 横屏切竖屏时,
vh突变但 resize 事件可能不触发(尤其 Safari),导致高度卡死
Chart.js 怎么配合 CSS 缩放不糊?
关键不是“让 canvas 跟着缩”,而是“让 canvas 主动重建并匹配设备像素比”。
- 初始化时传
devicePixelRatio: window.devicePixelRatio || 1,否则高分屏下默认按 1x 渲染 - 监听
ResizeObserver(比window.onresize更准,能捕获父容器变化):const ro = new ResizeObserver(() => chart.resize());<br>ro.observe(document.getElementById('myChart')); - 必须设
maintainAspectRatio: false,否则responsive: true会锁死宽高比,缩放时强行裁边 - 给容器加
min-width: 300px; min-height: 200px,防小屏下图例/坐标轴被压垮
ECharts 容器查询(@container)怎么真正生效?
容器查询不是“查屏幕”,是查父容器尺寸。它适合嵌入 Dashboard 卡片,但有两个硬性前提:
立即学习“前端免费学习笔记(深入)”;
- 父容器必须设
container-type: size(Firefox/Chrome 支持)或container-type: inline-size(Safari 16.4+ 仅此类型) - 图表容器自身不能是
height: auto,得设具体值(如height: 200px),否则容器查询无法计算 - 在
@container规则里改的是容器样式(如height或font-size),不是直接操作canvas元素 - 改完尺寸后,必须手动调
echart.resize({ silent: true }),且确保容器已 layout 完成(可用getBoundingClientRect()校验尺寸是否真变了)
容易被忽略的横竖屏与高分屏陷阱
横屏切换时,vh 值突变但 ResizeObserver 可能不触发;高分屏下 devicePixelRatio 若未透传,canvas 缓冲区永远是 1x 分辨率。
最稳的做法:放弃纯 CSS 缩放,用 ResizeObserver + 显式 resize() + devicePixelRatio 初始化三件套。容器用 width: 100% + min-height,别碰 transform: scale() —— 那只是把模糊放大而已。


















