普通视图

发现新文章,点击刷新页面。
今天 — 2026年2月3日首页

Three.js 适配的“保姆级”教程,拒绝拉伸和模糊!

作者 烛阴
2026年2月2日 23:44

第一步:CSS 铺满全屏

首先,我们要让 Canvas 元素本身在网页里占满位置。这步最简单,但是很关键,很多人容易漏掉 display: block

默认情况下,Canvas 是 inline 元素,这会导致它底部莫名其妙多出几像素的“留白”(就像文字的行高一样)。

✅ 正确的 CSS 写法:

html, body {
  margin: 0;
  height: 100%;
}

#c {
  width: 100%;  /* 宽度占满父容器 */
  height: 100%; /* 高度占满父容器 */
  display: block; /* 关键!去除底部留白 */
}

第二步:拒绝“暴力拉伸”

CSS 把 Canvas 拉大了,但 Canvas 内部的“绘图缓冲区”(Drawing Buffer)可能还停留在原来的大小。

这就好比你把一张 100x100 的低清图片,强行用 CSS 放大到 1920x1080 显示,结果必然是模糊马赛克

在渲染循环中检查 Three.js 官方推荐写一个通用函数,在每一帧渲染前检查 Canvas 的显示大小和实际大小是否一致。

function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  // 获取 Canvas 在屏幕上显示的像素宽
  const width = canvas.clientWidth;
  // 获取 Canvas 在屏幕上显示的像素高
  const height = canvas.clientHeight;
  
  // 检查渲染器的内部尺寸是否和显示尺寸一样
  const needResize = canvas.width !== width || canvas.height !== height;
  
  if (needResize) {
    // 如果不一样,就调整渲染器大小
    // 第三个参数 false 很重要!表示不要让渲染器去修改 Canvas 的 CSS 样式
    renderer.setSize(width, height, false);
  }
  
  return needResize;
}

第三步:告诉摄像机“别把人拍扁了”(校准)

解决了模糊问题,还有一个变形问题。

想象一下,你的显示器本来是宽屏(16:9),摄像机也是按 16:9 拍摄的。当你把窗口缩窄变成竖屏(9:16)时,如果摄像机不调整,它还是把 16:9 的画面强行塞进 9:16 的格子里,物体就会被横向挤压

所以,每当分辨率改变时,我们必须更新摄像机的 长宽比 (Aspect Ratio)

✅ 最终的渲染循环代码:

function render(time) {
  time *= 0.001;

  // 1. 检查并调整分辨率
  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    
    // 2. 修正摄像机长宽比
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    
    // 3. 必须调用这个方法,摄像机参数才会生效!
    camera.updateProjectionMatrix();
  }

  // 正常渲染
  renderer.render(scene, camera);
  
  requestAnimationFrame(render);
}

requestAnimationFrame(render);

📂 核心代码与完整示例:   my-three-app

总结

如果你喜欢本教程,记得点赞+收藏!关注我获取更多Three.js开发干货

❌
❌