Canvas高清屏适配关键是让物理绘制分辨率匹配设备DPR,保持CSS布局尺寸不变:动态获取DPR,设置canvas.width/height为CSS尺寸×DPR,style宽高设为CSS像素,并调用ctx.scale(dpr,dpr)统一坐标系。

网页端 Canvas 在多端适配高清屏(如 Retina、2K、4K 或高 DPR 的安卓/iOS 设备)时,核心不是“缩放比例”本身,而是让 Canvas 的物理绘制分辨率匹配设备真实像素密度,同时保持 CSS 布局尺寸不变。模糊本质是浏览器在低分辨率缓冲区上绘图后强行拉伸所致,解决关键在于 设备像素比(DPR)对齐 和 坐标系一致性。
动态获取并应用设备像素比(DPR)
这是适配的第一步,也是基础。不能写死 2 或 3,必须运行时读取:
- 用
window.devicePixelRatio获取当前设备的 DPR 值(iOS/Android/桌面 Chrome/Firefox 均支持) - 若值不可靠(如某些安卓 WebView 返回 1),可 fallback 到
matchMedia查询或通过 canvas 绘制测试像素验证 - 注意:DPR 可能随屏幕旋转、系统缩放设置或分屏模式变化,需监听
resize或devicePixelRatio变化(部分浏览器支持visualViewport事件)
正确设置 Canvas 的 width/height 与 style 尺寸
常见错误是直接写 canvas.width = 300,这等于固定了逻辑像素,忽略物理像素。应分离“显示尺寸”和“缓冲区尺寸”:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 用
getBoundingClientRect()获取 Canvas 在页面中的 CSS 像素宽高(即你希望它“看起来多大”) - 将
canvas.width和canvas.height设为:CSS宽 × DPR和CSS高 × DPR(这才是真实绘制缓冲区) - 显式设置
canvas.style.width和canvas.style.height为 CSS 像素值(如"300px"),确保布局不受影响 - 避免在 HTML 中硬编码
width/height属性,或在 Vue/React 中用响应式绑定覆盖 JS 设置(会引发冲突)
用 ctx.scale() 统一坐标系,避免手动换算
设置完缓冲区后,如果不调整绘图上下文,所有 fillRect(10,10,20,20) 都会按 CSS 像素画在放大后的缓冲区里,导致图形被压缩。因此必须缩放绘图坐标系:
- 调用
ctx.scale(dpr, dpr)—— 这样你写的坐标(如 x=10)就自动映射到 10×DPR 的物理像素位置 - 后续所有绘图操作(线条、文字、图片)都无需修改数值,逻辑完全保持“CSS 像素思维”
- 如果需要局部取消缩放(比如绘制 UI 控件),可用
ctx.save()/ctx.restore()配合反向 scale
补充细节:抗锯齿与图像资源对齐
DPR 适配只是基础,还需配合以下操作防止边缘发虚或内容错位:
- 绘制 1px 线条或细边框时,把坐标加 0.5:例如
ctx.strokeRect(Math.round(x) + 0.5, Math.round(y) + 0.5, w, h),确保落在物理像素中心 - 使用
drawImage()时,传入的源图尺寸尽量为 DPR 整数倍;若加载网络图片,优先提供 @2x/@3x 资源,并用img.width * dpr计算绘制尺寸 - 关闭不必要的插值:设
ctx.imageSmoothingEnabled = false(适合像素风、图标、矢量图形) - 文本渲染建议用
ctx.font指定绝对像素字号(如"16px sans-serif"),而非 rem/em,避免字体引擎二次缩放










