HTML5 Canvas高清屏适配的关键是按devicePixelRatio缩放canvas.width/height缓冲区,同时保持style.width/height显示尺寸不变;封装函数需分离CSS尺寸与绘图缓冲区,支持容器或canvas元素输入,并自动应用ctx.scale(dpr,dpr)。

<p>在 HTML5 Canvas 开发中,适配高清屏(如 Retina 屏)的关键是:**按设备像素比(<strong>window.devicePixelRatio</strong>)缩放画布的 <strong>canvas.width/height</strong>(绘图缓冲区),同时保持 <strong>canvas.style.width/height</strong>(显示尺寸)不变**。封装一个通用初始化函数,需兼顾兼容性、可复用性和语义清晰。</p> <h3>核心逻辑:分离 CSS 尺寸与绘图缓冲区尺寸</h3> <p>Canvas 渲染质量取决于其内部缓冲区像素数量(<code>width</code>/<code>height</code> 属性),而非 CSS 设置的显示大小。高清屏下若不放大缓冲区,图形会模糊。正确做法:</p>
- 获取目标容器(如 )的实际 CSS 宽高
- 用
window.devicePixelRatio计算实际绘制所需缓冲区尺寸- 设置
canvas.width和canvas.height为放大后值- 用
canvas.style.width和canvas.style.height控制显示大小(保持原始 CSS 尺寸)- 对 2D 上下文应用
ctx.scale(dpr, dpr),使绘图坐标系自动适配(避免手动换算)封装通用初始化函数(支持传入容器或 canvas 元素)
以下函数接受容器元素(或 canvas 元素本身),自动创建/获取 canvas,设置高清适配,并返回带上下文的配置对象:
htmlppt.skill下载把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
<code>function initHiDPICanvas(target, options = {}) { const { width = target.clientWidth || 300, height = target.clientHeight || 150, autoResize = true, scale = window.devicePixelRatio || 1 } = options; let canvas; if (target instanceof HTMLCanvasElement) { canvas = target; } else { canvas = target.querySelector('canvas') || document.createElement('canvas'); if (!target.querySelector('canvas')) target.appendChild(canvas); } const ctx = canvas.getContext('2d'); const dpr = scale; // 设置绘图缓冲区(物理像素) canvas.width = Math.floor(width * dpr); canvas.height = Math.floor(height * dpr); // 设置显示尺寸(CSS 像素) canvas.style.width = width + 'px'; canvas.style.height = height + 'px'; // 缩放上下文,使 drawRect(0,0,10,10) 仍画出 10×10 CSS 像素区域 ctx.scale(dpr, dpr); // 可选:监听窗口缩放,动态重置(适用于响应式场景) if (autoResize && target !== canvas) { const resizeHandler = () => { const rect = target.getBoundingClientRect(); canvas.width = Math.floor(rect.width * dpr); canvas.height = Math.floor(rect.height * dpr); canvas.style.width = rect.width + 'px'; canvas.style.height = rect.height + 'px'; ctx.scale(dpr, dpr); // 注意:此处需清空并重绘,或由调用方处理 }; window.addEventListener('resize', resizeHandler); // 返回销毁函数便于清理 return { canvas, ctx, destroy: () => window.removeEventListener('resize', resizeHandler) }; } return { canvas, ctx }; }</code>使用示例:一行代码完成高清初始化
HTML 中只需一个容器:
<code><div id="game-canvas" style="width: 800px; height: 600px;"></div></code>
JS 中调用:
<code>const { canvas, ctx } = initHiDPICanvas( document.getElementById('game-canvas'), { autoResize: true } ); // 此时可直接用 CSS 像素坐标绘图(无需乘 dpr) ctx.fillStyle = 'red'; ctx.fillRect(10, 10, 50, 30); // 实际绘制 50×30 物理像素,显示为 50×30 CSS 像素</code>注意事项与边界处理
-
devicePixelRatio 可能非整数(如 1.25、1.5),务必用
Math.floor取整,避免 canvas 尺寸非法 -
不要在 resize 后直接调用
ctx.scale()多次——每次重设宽高后需先ctx.setTransform(1,0,0,1,0,0)重置矩阵,再重新scale(dpr,dpr) -
WebGL 用户需额外设置
gl.viewport,本函数仅针对 2D;如需 WebGL 支持,应扩展判断getContext('webgl') - 服务端渲染或无 DOM 环境下需 fallback,例如默认 dpr=1,或通过 UA 字符串粗略判断
- 用
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










