Three.js使用ExtrudeGeometry拉伸时尺寸不符合预期问题
问题说明
使用threejs的ExtrudeGeometry做路径拉伸时,预期生成尺寸为12×8×12的几何体,实际渲染效果为细长杆,尺寸比例异常。
相关测试代码如下:
业务逻辑代码(script.js)
// ------------------------------------------------ // 基础初始化 // ------------------------------------------------ // 创建空场景 var scene = new THREE.Scene(); // 创建透视相机 var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); camera.position.z = 150; // 开启抗锯齿创建渲染器 var renderer = new THREE.WebGLRenderer({antialias:true}); // 设置渲染器清屏颜色 renderer.setClearColor("#000000"); // 设置渲染尺寸 renderer.setSize( window.innerWidth, window.innerHeight ); // 将渲染器挂载到页面 document.body.appendChild( renderer.domElement ); // ------------------------------------------------ // 核心逻辑 // ------------------------------------------------ function make_graphics(){ // 清空场景内已有物体 for( var i = scene.children.length - 1; i >= 0; i--) { obj = scene.children[i]; scene.remove(obj); } // 定义拉伸用的2D形状 const shape = new THREE.Shape(); const x_len = 12; const y_len = 8; shape.moveTo( 0, 0 ); shape.lineTo( 0, y_len ); shape.lineTo( x_len, y_len ); shape.lineTo( x_len, 0 ); shape.lineTo( 0, 0 ); // 拉伸参数配置 const extrudeSettings = { steps: 2, depth: 12, bevelEnabled: true, bevelThickness: 1, bevelSize: 1, bevelOffset: 0, bevelSegments: 1 }; // 生成拉伸几何体 const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings ); const material = new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe:true } ); const mesh = new THREE.Mesh( geometry, material ) ; scene.add( mesh ); // 渲染循环 var render = function () { requestAnimationFrame( render ); mesh.rotation.x += 0.001; mesh.rotation.y += 0.001; renderer.render(scene, camera); }; render(1, 1, 1); } document.addEventListener("DOMContentLoaded", function(){ make_graphics(); });
页面代码(index.html)
<html lang="en"> <head> <meta charset="UTF-8" /> <title>Three.js 101</title> <style> body { margin: 0; } canvas { width: 100%; height: 100% } </style> <script src="three.min.js"></script> </head> <body> <script src="script.js"></script> </body> </html>
原因分析
几何体本身生成逻辑没有问题,显示异常是渲染层面的问题,核心原因是canvas的CSS尺寸和内部渲染分辨率不匹配,同时缺少窗口尺寸变化的适配逻辑:
- 初始化时你调用
renderer.setSize给WebGL画布设置了和当前窗口一致的像素分辨率,但是CSS强制给canvas设置了width:100%;height:100%属性,一旦窗口尺寸和初始化时的尺寸不一致(比如浏览器地址栏占位、窗口缩放、初始化时机问题导致获取的inner宽高不准),canvas就会被CSS强制拉伸变形,连带画面里的几何体看起来比例失调,呈现细长杆的效果。 - 另外你开启了斜角(bevel)效果,实际生成的几何体尺寸会比预期略大:拉伸方向总厚度为
bevelThickness*2 + depth = 14,XY平面的长宽为(x_len + bevelSize*2) × (y_len + bevelSize*2) = 14×10,这个偏差很小,不是造成细长杆效果的原因。
修复方案
- 方案1:删除CSS里
canvas { width: 100%; height: 100% }的样式,让canvas保持渲染器输出的原始像素尺寸,不会被强制拉伸。 - 方案2:添加窗口resize监听,窗口尺寸变化时同步更新相机宽高比、投影矩阵和渲染器尺寸,代码如下:
window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); })
如果不需要斜角效果,将拉伸参数里的bevelEnabled设为false,就能得到和预期完全一致的12×8×12尺寸的几何体。
内容的提问来源于stack exchange,提问作者max
相关产品推荐
相关产品推荐

