#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 , вы можете использовать контекст для достижения своей цели.
- Сначала создайте контекст, который будет использоваться в качестве вашей одноэлементной ссылки. Экспортируются состояние и контекст реакции.
CesiumContext.js
export const state = {viewer: '', setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
- В каждом компоненте, который вы хотите иметь ссылку на экземпляр 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;
- В компоненте приложения отобразите ContextProvider с состоянием контекста. После
ViewComponent
рендеринга / монтирования и установки состояния контекста каждый дочерний компонент в элементе Context имеет доступ к текущему объекту представления Cesium. Существует проблема, созданная этой структурой, заключающаяся в том, что для того, чтобы это произошло, дерево должно быть повторно отображено. В зависимости от вашего приложения вам, возможно, придется принудительно выполнить повторный рендеринг.
App.js
<div className="App">
<CesiumContext.Provider value={state}>
<ViewerComponent/>
<AComponent/>
<BComponent/>
</CesiumContext.Provider>
</div>
- Наконец, в любых компонентах, требующих доступа к общему ресурсу (в данном случае к экземпляру 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.
Ответ №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 / … ), с которым я могу согласиться, если моя команда не согласится на рефакторинг: P3. Хуки используются в функциональных компонентах, а не в компонентах на основе классов. Я не уверен, чего вы хотите достичь. Но я надеюсь, что вы рассмотрите возможность голосования и принятия этого ответа.
4. Я хочу получить ссылку на объект viewer вне компонента, в котором он был создан.
5. Я прокомментировал до того, как появился ваш комментарий. поиск…