import { Meta, StoryObj } from "@storybook/react"; import { Cartesian2, Cartesian3, Color, KeyboardEventModifier, ScreenSpaceEventType, Viewer as CesiumViewer, } from "cesium"; import { useRef, useState } from "react"; import { CesiumComponentRef } from "../core"; import Entity from "../Entity"; import PointGraphics from "../PointGraphics"; import ScreenSpaceEventHandler from "../ScreenSpaceEventHandler"; import Viewer from "../Viewer"; import ScreenSpaceEvent from "./ScreenSpaceEvent"; type Story = StoryObj; export default { title: "ScreenSpaceEvent", component: ScreenSpaceEvent, } as Meta; type Marker = { id: number; position: Cartesian3; color: Color; label: string }; /** * Demonstrates plain, single-modifier, and chord-modifier bindings on the same * event type. Each binding drops a colored point on the globe at the click * location, so it's obvious which combination fired: * * - **Plain click** → red point * - **ALT + click** → yellow point * - **ALT + SHIFT + click** → cyan point (chord — requires Cesium 1.142+) * * The overlay also logs the last few events for confirmation. Clicks that miss * the globe (e.g. above the horizon) only update the log. */ export const Chord: Story = { render: () => { // eslint-disable-next-line react-hooks/rules-of-hooks const viewerRef = useRef>(null); // eslint-disable-next-line react-hooks/rules-of-hooks const counterRef = useRef(0); // eslint-disable-next-line react-hooks/rules-of-hooks const [markers, setMarkers] = useState([]); // eslint-disable-next-line react-hooks/rules-of-hooks const [log, setLog] = useState([]); const pickGlobe = (screen: Cartesian2): Cartesian3 | undefined => { const viewer = viewerRef.current?.cesiumElement; if (!viewer) return undefined; const ray = viewer.camera.getPickRay(screen); if (!ray) return undefined; const hit = viewer.scene.globe.pick(ray, viewer.scene); return hit ?? undefined; }; const handle = (label: string, color: Color) => (e: { position: Cartesian2 } | { startPosition: Cartesian2; endPosition: Cartesian2 }) => { if (!("position" in e)) return; setLog(prev => [...prev.slice(-5), label]); const position = pickGlobe(e.position); if (!position) return; const id = counterRef.current++; setMarkers(prev => [...prev.slice(-19), { id, position, color, label }]); }; return ( {markers.map(m => ( ))}
Try clicking the globe:
plain click
ALT + click
ALT + SHIFT + click (chord)
{log.length === 0 ?
· no events yet
: log.map((l, i) =>
· {l}
)}
); }, };