Canvas画面被拉伸是因为CSS宽高与实际像素尺寸分离,需用devicePixelRatio×getBoundingClientRect()动态设置canvas.width/height,并配合scaleFactor统一缩放游戏内元素。

Canvas 宽高设成 100% 为什么画面被拉伸?
因为 canvas 元素的 CSS 尺寸(width/height)和绘图上下文的实际像素尺寸(canvas.width/canvas.height)是两回事。只设 CSS 为 100% 会让画布被浏览器拉伸渲染,但绘图分辨率没变,结果就是模糊或变形。
- 必须显式设置
canvas.width和canvas.height为设备物理像素尺寸,比如window.devicePixelRatio * clientWidth - 监听
resize事件重置 canvas 像素尺寸,但注意别每帧都调用 —— 会频繁触发重排 - 用
getBoundingClientRect()拿实际显示区域尺寸,比clientWidth更准(尤其在缩放或 iframe 场景下)
viewport meta 标签写错会导致 touch 失效
很多 H5 游戏在 iPhone 上点不动,根本原因是 viewport 设置禁用了用户缩放,却没配对处理双指缩放或 touch 事件拦截逻辑。
- 至少要写:
- 如果游戏需要双指缩放,就得去掉
user-scalable=no,并自己用touchstart/touchmove解析 pinch 手势 -
maximum-scale=1.0在 iOS 10+ 已被忽略,仅靠它防缩放不可靠;真要锁死,得结合event.preventDefault()+touch-action: none
Phaser / PixiJS 等引擎的 scaleManager 不等于自适应
这些引擎的 scaleManager 或 resize 方法只是帮你改 canvas 尺寸和更新内部坐标系,不解决布局锚点、UI 缩放比例、字体清晰度等实际问题。
- Phaser 3 的
ScaleManager.RESIZE模式下,game.canvas尺寸变了,但场景中所有Sprite的scale还是 1 —— 你需要手动按比例调整 UI 元素位置 - PixiJS 的
app.renderer.resize()只重设渲染缓冲区,文字若用Text类且未设resolution: window.devicePixelRatio,在高 DPI 屏上会发虚 - 不要依赖引擎自动适配「设计稿宽高」,先确认你的设计基准是 750×1334 还是 375×667,再算缩放系数,否则按钮永远点不准
rem / vw 布局在 Canvas 游戏里基本没用
Canvas 是位图绘制,所有坐标、尺寸都是像素值。用 CSS 的 rem 或 vw 控制 canvas 外容器大小可以,但无法让游戏内角色、血条、文字跟着响应式缩放 —— 那些都在 canvas 像素坐标系里跑。
立即学习“前端免费学习笔记(深入)”;
- UI 层如果混用 DOM(比如弹窗、按钮),可以用
vw做字号,但 canvas 内部文字必须用ctx.font = '16px Arial'这种绝对像素值,再配合devicePixelRatio动态调整 - 想实现「等比缩放整个游戏画面」,得统一维护一个
scaleFactor,然后所有x/y/width/height都乘它,而不是指望 CSS 能透传到绘图 API - 横竖屏切换时,
orientationchange事件延迟高、不准,建议用matchMedia('(orientation: landscape)')监听更稳
最常被忽略的是:不同安卓厂商对 screen.orientation 和 devicePixelRatio 的实现差异极大,测试不能只看 Chrome 模拟器 —— 真机连小米、华为、OPPO 各测一遍,尤其是折叠屏展开后 canvas 尺寸回调是否触发两次。











