如何从文档中获取 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;

Reference

编辑:使用基于 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 来实现您的目标。

  1. 首先创建一个将用作您的单例引用的上下文。导出状态和 React 上下文。
CesiumContext.js
export const state = {viewer: '', setInstance: (ref)=>{state.viewer = ref;}};
export default CesiumContext;
  1. 在每个你想要引用 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;
  1. 在 App 组件中,使用上下文状态呈现 ContextProvider。一旦 ViewComponent renders/mounts 和 Context 状态被设置,那么 Context 元素下的每个子组件都可以访问当前的 Cesium View 对象。此结构会产生一个问题,即为了实现这一点,必须重新渲染树。根据您的应用程序,您可能必须强制重新渲染。
App.js
      <div className="App">
        <CesiumContext.Provider value={state}>
          <ViewerComponent/>
          <AComponent/>
          <BComponent/>
        </CesiumContext.Provider>
      </div>
  1. 最后,在任何需要访问共享资源的组件中(在本例中为 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 属性.

React Playground Solution