React + Three. js canvas не изменяет размер при уменьшении размера окна браузера - PullRequest
0 голосов
/ 09 января 2020

Я использую реагирование и три. 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);
}

Чего мне не хватает?

Ответы [ 2 ]

0 голосов
/ 11 января 2020

Так что после комментирования, я думаю, у меня получилось так, как вы хотите.

По сути,
Я удалил настройку display:flex в области просмотра, так как это дочерний элемент элемента (flex-row-container div) с display:flex, он не нужен, но действительно нужно flex:1 1 auto, чтобы установить, как оно будет отображаться во flexbox (что я и сделал в css, а не в JSX).
Затем возникла проблема, что div области просмотра будет расширяться, но не сжиматься (поскольку он содержит холст), поэтому добавление overflow:hidden исправило это.
После внесения этих изменений, this.mount.clientWidth получит желаемый результат, который затем можно будет использовать для установки размера трех холстов.

См. Эта скрипка .
Я добавил рендеринг и анимацию в пример, чтобы результат был легко виден.

Надеюсь, это поможет.

0 голосов
/ 09 января 2020

Возможно, вы получаете неправильные значения, используя element.clientWidth. Вы пытались использовать element.getBoundingClientRect() вместо?

const rect = this.mount.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...