如何从文档中获取 Cesium 查看器的实例?
How can I get an instance of the Cesium viewer from document?
我试过使用
var viewer = document.getElementById("cesiumContainer")
但这并不是 return 实际的查看器对象。为已经创建的查看器获取实例 of/reference 的正确方法是什么。我试图在我的代码的一部分中访问它,这部分代码超出了我创建查看器的部分的范围,如果那不是很明显的话。
查看器是使用 resium
包为带有 <Viewer>
的 React 应用程序创建的。呈现的 HTML 页面仍然将查看器包装在 ID 为 cesiumContainer
的 div 中,并且通过在开发工具中检查源代码,它看起来与没有反应时一样,所以我认为就能够访问它而言,它的行为是相同的。当然也可能不是这样。
文档指出,如果您从 resium
导入 useCesium
,则以下代码将获取您之后的引用。
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;
编辑:使用基于 Class 的组件需要以不同方式访问实例。以下是文档中的两个示例:
使用class方法:
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} />;
}
}
此答案主要关注您对 Resium、Cesium 和基于 class 的 React 组件的使用。
如果您使用的是 React 16+,则可以使用 Context 来实现您的目标。
- 首先创建一个将用作您的单例引用的上下文。导出状态和 React 上下文。
CesiumContext.js
export const state = {viewer: '', setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
- 在每个你想要引用 Cesium 实例的组件中,将 class 属性
contextType
设置为 React Contact 引用。 (CesiumContext
)。在 ViewerComponent 构造函数中使用 createRef()
。它将捕获唯一允许设置 Context 状态的 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 && this.ref.current.cesiumElement) {
this.context.setInstance(this.ref.current.cesiumElement);
}
}
render() {
return <Viewer ref={this.ref}/>
}
}
ViewerComponent.contextType = CesiumContext;
- 在 App 组件中,使用上下文状态呈现 ContextProvider。一旦
ViewComponent
renders/mounts 和 Context 状态被设置,那么 Context 元素下的每个子组件都可以访问当前的 Cesium View 对象。此结构会产生一个问题,即为了实现这一点,必须重新渲染树。根据您的应用程序,您可能必须强制重新渲染。
App.js
<div className="App">
<CesiumContext.Provider value={state}>
<ViewerComponent/>
<AComponent/>
<BComponent/>
</CesiumContext.Provider>
</div>
- 最后,在任何需要访问共享资源的组件中(在本例中为 Cesium View 实例),在 class 上设置
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 property and 'BComponent` accesses the Cesium.View. allowDataSourcesToSuspendAnimation 属性.
我试过使用
var viewer = document.getElementById("cesiumContainer")
但这并不是 return 实际的查看器对象。为已经创建的查看器获取实例 of/reference 的正确方法是什么。我试图在我的代码的一部分中访问它,这部分代码超出了我创建查看器的部分的范围,如果那不是很明显的话。
查看器是使用 resium
包为带有 <Viewer>
的 React 应用程序创建的。呈现的 HTML 页面仍然将查看器包装在 ID 为 cesiumContainer
的 div 中,并且通过在开发工具中检查源代码,它看起来与没有反应时一样,所以我认为就能够访问它而言,它的行为是相同的。当然也可能不是这样。
文档指出,如果您从 resium
导入 useCesium
,则以下代码将获取您之后的引用。
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;
编辑:使用基于 Class 的组件需要以不同方式访问实例。以下是文档中的两个示例:
使用class方法:
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} />;
}
}
此答案主要关注您对 Resium、Cesium 和基于 class 的 React 组件的使用。
如果您使用的是 React 16+,则可以使用 Context 来实现您的目标。
- 首先创建一个将用作您的单例引用的上下文。导出状态和 React 上下文。
export const state = {viewer: '', setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
- 在每个你想要引用 Cesium 实例的组件中,将 class 属性
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
renders/mounts 和 Context 状态被设置,那么 Context 元素下的每个子组件都可以访问当前的 Cesium View 对象。此结构会产生一个问题,即为了实现这一点,必须重新渲染树。根据您的应用程序,您可能必须强制重新渲染。
<div className="App">
<CesiumContext.Provider value={state}>
<ViewerComponent/>
<AComponent/>
<BComponent/>
</CesiumContext.Provider>
</div>
- 最后,在任何需要访问共享资源的组件中(在本例中为 Cesium View 实例),在 class 上设置
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 property and 'BComponent` accesses the Cesium.View. allowDataSourcesToSuspendAnimation 属性.