问题描述
我试过使用
var viewer = document.getElementById("cesiumContainer")
但这不会返回实际的查看器对象。获取已经创建的查看器的实例/引用的正确方法是什么。我正在尝试在我创建查看器的部分超出范围的代码中访问它,如果这不明显的话。
正在使用 resium
包为带有 <Viewer>
的 React 应用程序创建查看器。呈现的 HTML 页面仍然将查看器包装在一个 id 为 cesiumContainer
的 div 中,并且从开发工具中检查源代码来看,它看起来与没有反应的情况相同,所以我认为它在以下方面的行为是相同的能够访问它。当然,情况可能并非如此。
解决方法
这个答案侧重于您对 Resium、Cesium 和基于类的 React 组件的使用。
如果您使用的是 React 16+,则可以使用 Context 来实现您的目标。
- 首先创建一个上下文,用作您的单例引用。状态和 React Context 被导出。
export const state = {viewer: '',setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
- 在您想要引用 Cesium 实例的每个组件中,将类属性
contextType
设置为 React Contact 引用。 (CesiumContext
)。在 ViewerComponent 构造函数中使用createRef()
。它将捕获唯一允许设置 Context 状态的 prop (ref
),从而允许所有其他组件访问引用。请注意使用componentDidMount()
将上下文状态设置为 Resium 提供的引用。
export default class ViewerComponent extends React.Component {
constructor(props) {
super(props);
this.ref = createRef();
}
componentDidMount() {
if (this.ref.current && this.ref.current.cesiumElement) {
this.context.setInstance(this.ref.current.cesiumElement);
}
}
render() {
return <Viewer ref={this.ref}/>
}
}
ViewerComponent.contextType = CesiumContext;
- 在 App 组件中,使用上下文的状态呈现 ContextProvider。一旦
ViewComponent
渲染/挂载,并且设置了 Context 状态,那么 Context 元素下的每个子组件都可以访问当前的 Cesium View 对象。这种结构造成了一个问题,为了实现这一点,必须重新渲染树。根据您的应用,您可能需要强制重新渲染。
<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 属性。
文档表明,如果您从 amplify update api
导入 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;
使用 createRef:
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;
}}
/>
);
}
}