跳转到主内容
极星编程网:以代码为星,赴技术山海!

HTML5Canvas高清屏模糊_HTML5devicePixelRatio适配Retina屏幕教程【技巧】

Canvas在Retina屏发虚是因为未适配devicePixelRatio,需同步设置width/height属性为物理像素值并缩放绘图坐标,否则仅CSS缩放会导致插值模糊。 Canvas 在 Retina 屏上发虚是因为没处理
devicePixelRatio
浏览器默认用 1 个 CSS 像素对应 1 个物理像素,但 Retina 屏(如 MacBook、iPhone)的
devicePixelRatio
是 2 或 3——意味着 1 个 CSS 像素要铺开成 4 或 9 个物理像素。Canvas 的
width
/
height
属性是按物理像素设置的,而 CSS 样式(比如
style="width: 300px; height: 200px;"
)控制的是 CSS 像素。两者不匹配,浏览器只能靠插值拉伸,结果就是模糊。 必须同时改 canvas 元素的
width
和
height
属性,不能只改 CSS 只写
canvas.style.width = "300px"
不起作用:它只缩放显示区域,画布缓冲区还是原始大小,绘图内容被拉伸。真正要改的是 canvas 元素的 DOM 属性
width
和
height
(不是 CSS),让缓冲区物理像素数匹配设备密度。 实操建议: 读取
window.devicePixelRatio
,向下取整或四舍五入(通常用
Math.floor
避免小数导致渲染异常) 先保存原始 CSS 尺寸(比如
getComputedStyle(canvas).width
),再换算成物理像素值 赋值前清空 canvas(
ctx.clearRect(0, 0, canvas.width, canvas.height)
),否则旧缓冲区残留会干扰重绘 别在
resize
事件里频繁重设——加防抖,或者只在
devicePixelRatio
变化时响应(监听
matchMedia
的
"(resolution: ...dppx)"
更可靠)
ctx.scale(dpr, dpr)
是补救手段,不是替代方案 如果你已经用 CSS 控制了 canvas 大小,又不想动
width
/
height
属性,可以用
ctx.scale(dpr, dpr)
把所有绘图坐标放大。但它只是“骗”绘图 API,实际缓冲区仍不足,文字、线条抗锯齿效果差,且
getImageData
、
toDataURL
输出的仍是低分辩率图像。 立即学习 “ 前端免费学习笔记(深入) ”; 使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件 如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Andr​​oid友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Andr​​oid应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更 下载 常见错误现象: 文字边缘毛刺、小图标出现灰边——
scale
后没调用
ctx.font
重新设字号,或没对
lineWidth
手动乘
dpr
鼠标坐标错位——没把
clientX/clientY
除以
dpr
再传给
isPointInPath
动画卡顿——每帧都做
scale
+
translate
组合变换,不如直接提升缓冲区分辨率来得干净 兼容性与性能注意点:高
dpr
下内存和绘制成本陡增
devicePixelRatio
为 3 时,同样 300×200 CSS 尺寸的 canvas,缓冲区变成 900×600 物理像素,内存占用 ×9,
clearRect
和
drawImage
开销也显著上升。低端 Android 设备可能直接 OOM 或掉帧。 使用场景建议: 图标、图表、游戏主画布——值得适配;纯装饰性 canvas(比如背景粒子)可降级为
dpr = 1
服务端生成图片(
node-canvas
)不涉及
devicePixelRatio
,别套用这套逻辑 iOS Safari 15.4+ 支持
canvas.getContext("2d", { alpha: false })
提升性能,但和 dpr 无关,别混淆 最常被忽略的一点:canvas 元素插入 DOM 后才可读取
getComputedStyle
,动态创建时别在
new Canvas()
后立刻计算尺寸。

相关文章