You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:39:16