如何在Three.js中避免父物体缩放时子物体变形?
解决Three.js父物体缩放时子物体变形的问题
问题描述
我开发的Three.js程序包含父物体和若干子物体,对父物体进行单维度或多维度缩放时,子物体会随之变形:
- 缩放前效果:

- 子物体变形示例:

需求是父物体缩放时抵消子物体的缩放效果,但保留子物体跟随父物体移动的特性,因此无法解除父子关系。
之前尝试将子物体按1/父物体缩放比例反向缩放,但子物体尺寸过大且不准确,推测原因有两点:
- 父物体(6×9×1.75任意单位)与子物体原始尺寸比例不同,反向缩放公式需要额外参数调整
- 按1/父缩放比例调整后的效果:

- 按1/父缩放比例调整后的效果:
- 可通过Blender(制作.glb模型的工具)或Three.js本身锁定子物体尺寸,但Blender中操作未成功。
解决方案
一、Three.js代码层面精确抵消缩放
要准确抵消父物体缩放对子物体的影响,需要结合父物体的当前缩放值和子物体的初始缩放/尺寸计算反向缩放比例,步骤如下:
- 模型加载完成后,记录子物体和父物体的初始缩放:
// 遍历所有子物体,存储初始缩放 parent.children.forEach(child => { child.userData.initialScale = child.scale.clone(); }); // 存储父物体初始缩放 parent.userData.initialScale = parent.scale.clone();
- 在父物体缩放变化时(比如渲染循环或缩放控制的回调中),实时更新子物体缩放:
function syncChildScale() { const parentScale = parent.scale; const parentInitial = parent.userData.initialScale; // 计算父物体各轴的缩放变化比例 const scaleXRatio = parentScale.x / parentInitial.x; const scaleYRatio = parentScale.y / parentInitial.y; const scaleZRatio = parentScale.z / parentInitial.z; parent.children.forEach(child => { const initial = child.userData.initialScale; // 子物体反向缩放,抵消父物体缩放影响 child.scale.set( initial.x / scaleXRatio, initial.y / scaleYRatio, initial.z / scaleZRatio ); }); } // 在渲染循环中调用,实时同步 function animate() { requestAnimationFrame(animate); syncChildScale(); renderer.render(scene, camera); }
这样处理后,子物体将始终保持原始尺寸,同时正常跟随父物体移动和旋转。
二、Blender模型层面设置
如果希望从模型源头上解决,在Blender中按以下步骤操作:
- 选中子物体,进入物体模式,按
Ctrl+A选择应用缩放,将子物体的缩放值重置为(1,1,1) - 打开右侧属性面板(N键),找到物体关系选项卡
- 在继承变换区域,取消勾选缩放选项
- 重复上述步骤处理所有子物体后,导出为.glb格式
导入Three.js后,父物体缩放时子物体不会继承缩放属性,但仍会跟随父物体移动,完美满足需求。如果之前操作失败,大概率是没先应用子物体的缩放就取消继承,导致缩放数据残留。
内容的提问来源于stack exchange,提问作者joo0k
相关产品推荐
相关产品推荐

