Three.js 入门:在技术博客中嵌入一个不会空白的 3D 场景
本文目录
文章里的 3D 预览首先是内容阅读体验,其次才是渲染技术。首屏应先显示说明、封面和加载状态;用户进入可视区域或主动点击后再加载 Three.js 与模型,失败时保留静态图和可访问的文字描述。
不空白的最小条件
基础结构包括 Scene、Camera、Renderer、几何体/模型、材质与灯光。容器必须有非零宽高;相机 aspect、near/far、位置和 lookAt 要覆盖模型边界;材质是否受光、Canvas 是否被 CSS 隐藏、异步模型是否成功加载都需逐项确认。
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 1.5));
const resize = () => {
const rect = canvas.parentElement.getBoundingClientRect();
if (!rect.width || !rect.height) return;
camera.aspect = rect.width / rect.height;
camera.updateProjectionMatrix();
renderer.setSize(rect.width, rect.height, false);
};
const observer = new ResizeObserver(resize);
observer.observe(canvas.parentElement);
resize();
renderer.setAnimationLoop(() => renderer.render(scene, camera));
画布隐藏再显示、侧栏展开、字体加载和移动端旋转都可能改变容器尺寸。观察真实容器而不只监听 window resize;DPR 要设上限,避免高分辨率手机让像素成本平方级增加。
模型加载与文章安全
GLTF/GLB 是常见交换格式,但文件仍可能很大、损坏或引用外部资源。服务端限制扩展名、内容签名、大小和资源总量;解析器放在延迟加载边界,限制纹理尺寸、动画数量和总三角形预算。外部模型的许可、来源、更新时间和是否包含个人/商业数据必须清楚。
不要把作者可编辑 HTML、外链 URL 或任意脚本直接带进 WebGL viewer。下载模型只允许可信存储地址;跨域纹理要明确 CORS。模型加载进度、错误、超时和取消都有可见状态,读屏用户能获得模型简介或截图替代。
移动端交互和帧预算
使用 pointer/touch 兼容输入,给旋转、缩放和重置设置直观控件;不要只提供 hover 交互。支持暂停动画、静态模式与 prefers-reduced-motion;不活跃标签页可暂停渲染。避免默认自动播放复杂场景,且不要让 Canvas 截获文章滚动或键盘焦点。
控制几何细节、纹理压缩、材质数量、阴影、后期效果与渲染分辨率。以低端手机实测加载字节、首帧耗时、帧时间、GPU 内存和温升;设备能力检测只作为降级提示,不要基于 UA 字符串猜测性能。
生命周期与释放
ResizeObserver、动画循环、加载请求、控制器监听器、renderer、geometry、material、texture 和 render target 都有各自生命周期。文章路由切换、弹窗关闭和卸载时停止 animation loop、断开 observer、取消可取消请求、dispose 不再复用的 GPU 对象并移除 Canvas。资源可能被多个 mesh 共享,先明确所有权再释放,避免共享资源提前 dispose。
用 WebGLRenderer.info 观察几何体、纹理与 draw call 是否随重复打开/关闭持续增长;测试模型中途失败、WebGL context lost、无 GPU、快速切文章和返回页面。不要只检查 canvas 存在就判定场景健康。
参考:Three.js WebGLRenderer、Three.js Object3D、Three.js GLTFLoader。
Live Notes
留言提交后会先进入审核,审核通过后对其他读者公开。