canvas 高清适配需用 devicepixelratio × visualviewport.scale 计算 finalscale,并同步更新 canvas.width/height、style 尺寸及 ctx.scale,坐标仍按 css 像素书写,但 linewidth、font 等需手动乘 finalscale,交互坐标须除 finalscale 还原。

调整 Canvas 绘图上下文的 scale 比例,核心不是“随便放大”,而是让 逻辑坐标书写方式不变,同时确保所有绘制内容在高 DPR 屏上物理像素对齐、清晰不虚、位置准确。
scale 值怎么定:必须是 devicePixelRatio × 浏览器缩放系数
仅用 window.devicePixelRatio 不够——它只反映设备物理像素密度,不包含用户手动缩放(如 Ctrl+ 或系统字体缩放)。真实缩放因子应为:
- 基础值:const dpr = window.devicePixelRatio || 1
-
浏览器缩放系数:通过
visualViewport.scale(推荐)或ResizeObserver + getComputedStyle计算出 zoom - 最终 scale 值:const finalScale = dpr * (visualViewport?.scale || 1)
scale 必须和 canvas 尺寸、CSS 显示尺寸同步更新
单独调用 ctx.scale(x, y) 而不改 canvas.width/height 或 style 尺寸,会导致严重错位或拉伸。三者需原子化处理:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 重设缓冲区:
canvas.width = rect.width * finalScale;canvas.height = rect.height * finalScale - 固定显示区域:
canvas.style.width = rect.width + "px";canvas.style.height = rect.height + "px" - 重置绘图上下文:
ctx.clearRect(0, 0, canvas.width, canvas.height)后,立即执行ctx.scale(finalScale, finalScale)
scale 后所有坐标仍按 CSS 像素写,但样式要同步缩放
启用 ctx.scale() 的意义,就是让你继续用 fillRect(10, 20, 100, 50) 这类“看起来像 10px 宽”的代码,而不用改成 fillRect(20, 40, 200, 100)。但以下样式属性不会自动缩放,必须手动乘 finalScale:
ctx.lineWidth = 1 * finalScalectx.font = (14 * finalScale) + "px sans-serif"ctx.shadowBlur = 4 * finalScale- 文字对齐仍用
ctx.textAlign = "center"、ctx.textBaseline = "middle",y 坐标传入 CSS 像素值(如 100),无需再除 finalScale
交互点坐标也要反向适配
触摸或鼠标事件返回的是 CSS 像素坐标(比如 touch.clientX),而 ctx.isPointInPath() 等判断是在已缩放的坐标系里运行的。所以必须把原始坐标“还原”到缩放前:
- 正确写法:
ctx.isPointInPath(touchX / finalScale, touchY / finalScale) - 错误写法:
ctx.isPointInPath(touchX, touchY)(会偏移 2–3 倍) - 同理,
getBoundingClientRect()获取的 rect.left/top 也要除 finalScale 才能用于路径命中检测
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










