【发布时间】:2020-04-26 15:43:42
【问题描述】:
我正在使用 react 和 three.js 在浏览器中显示一些 3D 模型。只要 three.js 组件是页面上唯一具有可见内容的元素,一切都可以正常工作。 three.js 画布将调整大小变得越来越小就好了。您可以将其包装在其他容器中,它仍然可以正常工作。当另一个元素或组件作为同级添加时,问题就开始了。
我想要一个具有固定宽度侧边栏的视口。我正在使用一个 flexbox 行容器来执行此操作,该容器围绕一个侧边栏组件(一个设置了最小宽度的简单 div)和响应式 three.js 组件。
将窗口调整得更大可以正常工作,画布会适当地填充浏览器窗口。但是,当将窗口大小调整为较小时,画布不会正确地重新计算与静态宽度侧边栏剩余的可用空间相关的大小,从而导致画布不能完全适合浏览器并引入滚动条。
画布确实缩小了一些,但不足以将其完全保留在浏览器窗口中。如果一个组件位于three.js 组件的上方或下方,则垂直方向也会出现同样的问题。如果您在浏览器窗口较小时重新编译应用程序,刷新后的视图将正确调整画布大小。
根据 StackOverflow 上许多答案的建议,three.js 反应代码如下所示:
export class Viewport extends React.Component {
componentDidMount() {
const width = this.mount.clientWidth;
const height = this.mount.clientHeight;
window.addEventListener("resize", this.handleWindowResize);
// setup scene
this.scene = new THREE.Scene();
//setup camera
this.camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );
this.camera.position.set( 0, 5, 10 );
// setup rendering
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setClearColor('#666666');
this.renderer.setSize(width, height, false);
this.mount.appendChild(this.renderer.domElement);
// setup geo
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: '#433F81' });
this.cube = new THREE.Mesh(geometry, material);
this.scene.add(this.cube);
...
}
componentWillUnmount() {
window.removeEventListener("resize", this.handleWindowResize);
this.mount.removeChild(this.renderer.domElement);
}
handleWindowResize = () => {
const width = this.mount.clientWidth;
const height = this.mount.clientHeight;
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(width, height, false);
};
render() {
return (
<div className="viewport" style={{display: 'flex', width: "100%", height: "100%"}} ref={(mount) => { this.mount = mount }} />
);
}
}
样式是简单的 css flexbox,元素设置为全宽和全高 (100%),侧边栏设置最小宽度。
.flex-row-container {
display: flex;
flex-flow: row;
height: 100%;
width: 100%;
}
.sidebar {
display: block;
min-width: 250px;
background-color: var(--color-mid-gray);
margin: 3px 4px 3px 4px;
box-sizing: border-box;
border: 1px solid var(--color-mid-gray);
outline: 3px solid var(--color-mid-gray);
}
我错过了什么?
【问题讨论】:
-
为什么要在包含一个项目的 div 上使用
display:flex,即画布?这个 div 不是已经在带有display:flex的 div 中了吗(我们无法从您的代码中看到。)。如果是这种情况,那么我希望包含画布的 div 具有 flexbox 项 css,例如。flex-basis, flex-grow etc.,不是display:flex。 -
父 div 确实是 display:flex。在视口 div 上没有 display:flex 时,three.js 画布在编译或整页刷新时不会完全填满容器。将其切换到 flex item css 实际上会使重新调整大小变得更糟。这很古怪。我确定这很微妙,我只是还不知道是什么。
标签: reactjs three.js autoresize