Как я могу получить экземпляр средства просмотра Cesium из документа?

#javascript #reactjs #dom #getelementbyid #cesium

#javascript #reactjs #dom #getelementbyid #cesium

Вопрос:

Я пытался использовать

var viewer = document.getElementById("cesiumContainer")

но это не возвращает фактический объект просмотра. Каков правильный подход для получения экземпляра / ссылки на средство просмотра, которое уже было создано. Я пытаюсь получить к нему доступ в той части моего кода, которая выходит за рамки той части, где я создал средство просмотра, если это не было очевидно.

Средство просмотра создается с использованием resium пакета для приложения react <Viewer> . HTML-страница, которая отображается, по-прежнему обертывает средство просмотра в div с идентификатором cesiumContainer , и при проверке источника в инструментах разработки он выглядит так же, как и без react, поэтому я думаю, что он будет вести себя так же с точки зрения возможности доступа к нему. Конечно, это может быть не так.

Комментарии:

1. Как был Cesium.Viewer создан экземпляр?

2. Это было сделано в приложении react с использованием resium пакета. Я надеюсь получить к нему прямой доступ в другом компоненте react (отображаемом на той же странице, в том же DOM) без необходимости беспорядочно передавать ссылку в реквизитах.

Ответ №1:

В этом ответе основное внимание уделяется использованию компонентов Resium, Cesium и React на основе классов.

Если вы используете React 16 , вы можете использовать контекст для достижения своей цели.

  1. Сначала создайте контекст, который будет использоваться в качестве вашей одноэлементной ссылки. Экспортируются состояние и контекст реакции.

CesiumContext.js

 export const state = {viewer: '', setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
 
  1. В каждом компоненте, который вы хотите иметь ссылку на экземпляр Cesium, установите для свойства класса contextType ссылку на контакт с реакцией. ( CesiumContext ). В конструкторе ViewerComponent используйте createRef() . Он захватит единственный prop ( ref ), который позволит установить состояние контекста, тем самым предоставляя всем остальным компонентам доступ к ссылке. Обратите внимание на использование componentDidMount() для установки состояния контекста на ссылку, предоставленную Resium.

ViewerComponent.js

 export default class ViewerComponent extends React.Component {
  constructor(props) {
    super(props);
    this.ref = createRef();
  }
  componentDidMount() {
    if (this.ref.current amp;amp; this.ref.current.cesiumElement) {
      this.context.setInstance(this.ref.current.cesiumElement);
    }
  }
  render() {
    return <Viewer ref={this.ref}/>
  }
}
ViewerComponent.contextType = CesiumContext;
 
  1. В компоненте приложения отобразите ContextProvider с состоянием контекста. После ViewComponent рендеринга / монтирования и установки состояния контекста каждый дочерний компонент в элементе Context имеет доступ к текущему объекту представления Cesium. Существует проблема, созданная этой структурой, заключающаяся в том, что для того, чтобы это произошло, дерево должно быть повторно отображено. В зависимости от вашего приложения вам, возможно, придется принудительно выполнить повторный рендеринг.

App.js

       <div className="App">
        <CesiumContext.Provider value={state}>
          <ViewerComponent/>
          <AComponent/>
          <BComponent/>
        </CesiumContext.Provider>
      </div>
 
  1. Наконец, в любых компонентах, требующих доступа к общему ресурсу (в данном случае к экземпляру Cesium View), установите contextType для класса. В componentDidMount захвате экземпляра из контекста.

Любой компонент

 export default class AComponent extends React.Component {
  constructor() {
    super();
    this.viewer = false;
  }

  componentDidMount() {
    this.viewer = this.context.viewer;
  }
  render() {
    return <p>{/* do something with this.viewer */}</p>;
  }
}
AComponent.contextType = CesiumContext;
 

Полное решение демонстрирует это ниже. Один компонент AComponent обращается к свойству Cesium.View.shadowed, а ‘BComponent` обращается к свойству Cesium.View. Свойство allowDataSourcesToSuspendAnimation.

Решение для игровой площадки React

Ответ №2:

В документах указано, что если вы импортируете useCesium из resium , следующий код захватит ссылку, которую вы ищете.

 import { Viewer } from "cesium";
import { useCesium } from "resium";
const ExampleComponent = () => {
  const { viewer } = useCesium();
  return <p>Cesium Viewer object is{viewer ? "" : " not"} provided here.</p>;
};
export default ExampleComponent;
 

Ссылка

Редактировать: использование компонентов на основе классов требует другого доступа к экземпляру. Вот два примера из документации:

Использование метода класса:

 import React, { Component } from "react";
import { Viewer as CesiumViewer } from "cesium";
import { Viewer } from "resium";
class ExampleComponent extends Component {
  private viewer: CesiumViewer | undefined;
  componentDidMount() {
    if (this.viewer) {
      // this.viewer is Cesium's Viewer
      // DO SOMETHING
    }
  }
  render() {
    return (
      <Viewer
        ref={e => {
          this.viewer = e ? e.cesiumElement : undefined;
        }}
      />
    );
  }
}
 

Использование createRef:

 import React, { Component, createRef } from "react";
import { Viewer as CesiumViewer } from "cesium";
import { Viewer } from "resium";
class ExampleComponent extends Component {
  private ref = createRef<CesiumViewer | undefined>();
  componentDidMount() {
    if (this.ref.current?.cesiumElement) {
      // this.ref.current.cesiumElement is Cesium's Viewer
      // DO SOMETHING
    }
  }
  render() {
    return <Viewer ref={this.ref} />;
  }
}
 

Комментарии:

1. Спасибо, что нашли это! Похоже, что для того, чтобы использовать это, мне нужно будет провести рефакторинг функциональных компонентов или выполнить какой-либо другой обходной путь, чтобы использовать хук в компоненте класса…

2. useCesium это перехват, согласно этим документам. Попытка использовать его в компоненте класса выдала ошибку. Я нашел это обходное решение ( infinum.com/the-capsized-eight / … ), с которым я могу согласиться, если моя команда не согласится на рефакторинг: P

3. Хуки используются в функциональных компонентах, а не в компонентах на основе классов. Я не уверен, чего вы хотите достичь. Но я надеюсь, что вы рассмотрите возможность голосования и принятия этого ответа.

4. Я хочу получить ссылку на объект viewer вне компонента, в котором он был создан.

5. Я прокомментировал до того, как появился ваш комментарий. поиск…