简体   繁体   English

如何从文档中获取 Cesium 查看器的实例?

[英]How can I get an instance of the Cesium viewer from document?

I have tried using我试过使用

var viewer = document.getElementById("cesiumContainer")

but this doesn't return the actual viewer object.但这不会返回实际的查看器 object。 What's the correct approach to get an instance of/reference to the viewer that's been created already.获取已经创建的查看器的实例/引用的正确方法是什么。 I'm trying to get access to it in a part of my code that is out of scope with the part where I created the viewer, if that wasn't obvious.我试图在我创建查看器的部分 scope 之外的部分代码中访问它,如果这不明显的话。

The viewer is being created using the resium package for a react app with <Viewer> .正在使用resium package 为带有<Viewer>的反应应用程序创建查看器。 The HTML page that renders still wraps the viewer in a div with the id cesiumContainer and from inspecting the source in dev tools it looks the same as it would without react, so I would think it would behave the same in terms of being able to access it.呈现的 HTML 页面仍然将查看器包装在 div 中,id cesiumContainer并且通过在开发工具中检查源代码,它看起来与没有反应的情况相同,所以我认为它在能够访问方面表现相同它。 Of course that may not be the case.当然,情况可能并非如此。

This answer focuses on your use of Resium, Cesium and class based React Components.这个答案的重点是你使用 Resium、Cesium 和 class 基于 React 组件。

If you are using React 16+ you can use Context to achieve your goal.如果你使用 React 16+,你可以使用Context来实现你的目标。

  1. First create a context that will be used as your singleton reference.首先创建一个将用作 singleton 参考的上下文。 The state and React Context are exported. state 和 React Context 被导出。
CesiumContext.js CesiumContext.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. In every component you want to have a reference to the Cesium instance, set the class property contextType to the React Contact reference.在每个想要引用 Cesium 实例的组件中,将 class 属性contextType设置为 React Contact 引用。 ( CesiumContext ). CesiumContext )。 In the ViewerComponent constructor use createRef() .在 ViewerComponent 构造函数中使用createRef() It will capture the only prop ( ref ) that will allow the Context state to be set, thereby allowing all other components access to the reference.它将捕获允许设置上下文 state 的唯一道具 ( ref ),从而允许所有其他组件访问参考。 Note the use of componentDidMount() to set the state of the context to there reference provided by Resium.请注意使用componentDidMount()将上下文的 state 设置为 Resium 提供的参考。
ViewerComponent.js 查看器组件.js
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;
  1. In the App component, render the ContextProvider with the state of the context.在 App 组件中,使用上下文的 state 渲染 ContextProvider。 Once the ViewComponent renders/mounts, and the Context state is set, then every Child component under the Context element has access to the current Cesium View object.一旦ViewComponent渲染/挂载,并且设置了 Context state,那么 Context 元素下的每个子组件都可以访问当前的 Cesium View object。 There is a problem created by this structure in that in order for this to happen, the tree must be rerendered.这种结构产生了一个问题,为了实现这一点,必须重新渲染树。 Based upon your app you may have to force the rerendering.根据您的应用,您可能必须强制重新渲染。
App.js 应用程序.js
 <div className="App"> <CesiumContext.Provider value={state}> <ViewerComponent/> <AComponent/> <BComponent/> </CesiumContext.Provider> </div>
  1. Finally, in any components requiring access to the shared resource (Cesium View instance in this case), set contextType on the class.最后,在任何需要访问共享资源的组件(本例中为 Cesium View 实例)中,在 class 上设置contextType In the componentDidMount grab the instance from the context.componentDidMount从上下文中获取实例。
Any Component 任何组件
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;

A complete solution demonstrates this below.一个完整的解决方案在下面演示了这一点。 One component AComponent accesses the Cesium.View.shadowed property and 'BComponent` accesses the Cesium.View.一个组件AComponent访问Cesium.View.shadowed属性,而“BComponent”访问Cesium.View。 allowDataSourcesToSuspendAnimation property. allowDataSourcesToSuspendAnimation属性。

React Playground Solution React Playground 解决方案

The docs indicate that if you import useCesium from resium then the following code will grab the reference you are after.文档表明,如果您从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 参考

Edit: using Class based components requires accessing the instance differently.编辑:使用基于 Class 的组件需要以不同的方式访问实例。 Here are two samples from the documentation:以下是文档中的两个示例:

Using a class method:使用 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;
        }}
      />
    );
  }
}

Using createRef:使用 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} />;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM