UNPKG

resium

Version:

React components for Cesium

201 lines (182 loc) 5.1 kB
import { ReactNode, CSSProperties } from "react"; import { Viewer as CesiumViewer, ImageryProvider } from "cesium"; import { createCesiumComponent, EventManager, eventManagerContextKey, RootEventProps, PickCesiumProps, Merge, } from "../core"; /* @summary `Viewer` is a root component of resium same as `CesiumWidget`. All components of resium except the root components have to be mounted inside it. */ /* @example <Viewer full animation={false} timeline={false} /> */ /* @scope Everywhere. `Viewer` is a root component. */ export type ViewerCesiumProps = PickCesiumProps<CesiumViewer, typeof cesiumProps>; export type ViewerCesiumReadonlyProps = Merge< PickCesiumProps<Merge<CesiumViewer, CesiumViewer.ConstructorOptions>, typeof cesiumReadonlyProps>, { /** If false, the default imagery layer will be removed. */ imageryProvider?: ImageryProvider | false; } >; export type ViewerCesiumEvents = { onSelectedEntityChange?: () => void; onTrackedEntityChange?: () => void; }; const cesiumProps = [ "terrainProvider", "terrainShadows", "clockTrackedDataSource", "targetFrameRate", "useDefaultRenderLoop", "resolutionScale", "allowDataSourcesToSuspendAnimation", "trackedEntity", "selectedEntity", "shadows", "useBrowserRecommendedResolution", ] as const; const cesiumReadonlyProps = [ "animation", "baseLayerPicker", "fullscreenButton", "vrButton", "geocoder", "homeButton", "infoBox", "sceneModePicker", "selectionIndicator", "timeline", "navigationHelpButton", "navigationInstructionsInitiallyVisible", "scene3DOnly", "shouldAnimate", "clockViewModel", "selectedImageryProviderViewModel", "imageryProviderViewModels", "selectedTerrainProviderViewModel", "terrainProviderViewModels", "imageryProvider", "skyBox", "skyAtmosphere", "fullscreenElement", "showRenderLoopErrors", "automaticallyTrackDataSourceClocks", "contextOptions", "sceneMode", "mapProjection", "globe", "orderIndependentTranslucency", "creditContainer", "creditViewport", "dataSources", "terrainExaggeration", "mapMode2D", "projectionPicker", "requestRenderMode", "maximumRenderTimeChange", ] as const; export const cesiumEventProps = { onSelectedEntityChange: "selectedEntityChanged", onTrackedEntityChange: "trackedEntityChanged", } as const; export type ViewerOtherProps = RootEventProps & { /** Applied to outer `div` element */ className?: string; /** Applied to outer `div` element */ id?: string; /** Applied to outer `div` element */ style?: CSSProperties; /** Same as `style={{ position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }}` if it is true. */ full?: boolean; /** All props applied to outer `div` element */ containerProps?: any; /** It is applied in order from the top to Viewer as `viewer.extend(XXX);` after the viewer is mounted. Nothing happens even it is updated by itself. */ extend?: CesiumViewer.ViewerMixin[] | CesiumViewer.ViewerMixin; children?: ReactNode; }; export type ViewerProps = ViewerCesiumProps & ViewerCesiumReadonlyProps & ViewerCesiumEvents & ViewerOtherProps; const Viewer = createCesiumComponent<CesiumViewer, ViewerProps, EventManager>({ name: "Viewer", create(_context, { imageryProvider, ...props }, wrapper) { if (!wrapper) return; const v = new CesiumViewer(wrapper, { ...props, imageryProvider: imageryProvider === false ? undefined : imageryProvider, }); if (!v) return; if (imageryProvider === false) { v.imageryLayers.removeAll(); } if (v && props.extend) { if (Array.isArray(props.extend)) { props.extend.forEach(e => { v.extend(e, {}); }); } else { v.extend(props.extend, {}); } } // common event manager for managing events of Entity and Primitives const state = new EventManager(v.scene); return [v, state]; }, destroy(element, _context, _ref, state) { if (state && !state.isDestroyed()) { state.destroy(); } if (!element.isDestroyed()) { element.destroy(); } }, provide(element, _props, state) { return { viewer: element, cesiumWidget: element.cesiumWidget, dataSourceCollection: element.dataSources, entityCollection: element.entities, scene: element.scene, camera: element.scene.camera, imageryLayerCollection: element.scene.globe.imageryLayers, primitiveCollection: element.scene.primitives, globe: element.scene.globe, [eventManagerContextKey]: state, }; }, containerProps: ({ id, className, style, full, containerProps }) => ({ className, id, style: { ...(full ? { position: "absolute", bottom: "0", left: "0", right: "0", top: "0", } : {}), ...style, }, ...containerProps, }), cesiumProps, cesiumReadonlyProps, cesiumEventProps, renderContainer: true, useCommonEvent: true, useRootEvent: true, }); export default Viewer;