React中如何裁剪Three.js canvas且不产生缩放拉伸变形
解决方案
你遇到的变形问题本质是渲染画布尺寸和相机宽高比不匹配导致的,Three.js 不会自动同步相机参数和渲染画布的尺寸变化,仅修改renderer.setSize就会出现拉伸/挤压问题。
方案1:内容等比缩放适配横幅(无变形,完整显示场景内容)
如果希望场景内容完整显示在横幅区域内,仅调整整体比例为横幅样式,操作如下:
- 确定横幅高度:可以按比例计算(比如16:9横幅)或者固定高度
- 修改渲染尺寸的同时,同步更新相机宽高比和投影矩阵
示例代码:
// 以16:9比例横幅为例,宽度保持全屏 const bannerHeight = window.innerWidth * 9 / 16 // 固定高度写法:const bannerHeight = 400 // 更新渲染器尺寸 renderer.setSize(window.innerWidth, bannerHeight) // 同步更新相机宽高比 camera.aspect = window.innerWidth / bannerHeight // 相机参数修改后必须调用该方法才会生效 camera.updateProjectionMatrix()
方案2:垂直裁剪场景内容(内容不缩放,仅裁掉上下超出部分)
如果希望场景水平方向显示范围和全屏时完全一致,仅裁剪垂直方向超出横幅高度的内容,不需要修改相机参数,用视口配置即可:
const bannerHeight = 400 // 你需要的横幅高度 // 渲染器保持全屏尺寸 renderer.setSize(window.innerWidth, window.innerHeight) // 设置渲染视口,仅渲染垂直方向从底部到bannerHeight的区域,x轴保持满宽 renderer.setViewport(0, window.innerHeight - bannerHeight, window.innerWidth, bannerHeight)
同时给canvas的父容器添加样式,避免超出部分显示:
.three-banner-wrap { width: 100vw; height: 400px; overflow: hidden; } .three-banner-wrap canvas { display: block; }
React组件注意事项
- 以上逻辑需要同时写到组件初始化和窗口
resize事件的回调中,避免窗口尺寸变化时再次出现变形 - 不要给canvas元素单独设置CSS宽高,所有显示尺寸控制通过父容器实现,避免二次拉伸
内容的提问来源于stack exchange,提问作者QS123
相关产品推荐
相关产品推荐

