Я использую реагирование и три. js для отображения некоторых 3D-моделей в браузере. Все работает нормально, пока компонент. js является единственным элементом с видимым содержимым на странице. Три. js холст будет изменять размер больше и меньше, просто отлично. Вы можете обернуть его в другие контейнеры, и он все еще работает нормально. Проблема начинается, когда другой элемент или компонент добавляется как брат.
Я хочу иметь область просмотра с боковой панелью фиксированной ширины. Я делаю это с контейнером строк flexbox, обернутым вокруг компонента боковой панели (простой div с набором минимальной ширины) и отзывчивым компонентом 3. js.
Изменение размера окна больше работает нормально, холст заполняет окно браузера соответствующим образом. Однако при уменьшении размера окна холст неправильно рассчитывает его размер по отношению к доступному пространству, оставленному боковой панелью stati c, в результате холст не полностью умещается в браузере и появляются полосы прокрутки. .
Холст немного сжимается, но не настолько, чтобы полностью удерживать его в окне браузера. Та же проблема возникает по вертикали, если компонент находится над или под компонентом 3. js. Если вы перекомпилируете приложение, когда окно браузера меньше, обновленное представление будет иметь правильное изменение размера холста.
Следуя советам многих ответов здесь, в StackOverflow, код реакции. 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);
}
Чего мне не хватает?