如何将 onClick 行为添加到 Resium PointPrimitiveCollection 中的 Cesium PointPrimitive?

How do I add onClick behavior to a Cesium PointPrimitive in a Resium PointPrimitiveCollection?

提问人:ResiumRegent 提问时间:7/22/2023 更新时间:7/22/2023 访问量:83

问:

我希望添加到地图的 pointPrimitives 具有 onClick 行为。 Resium pointPrimitives 在作为子项添加到 PointPrimitiveCollection 时具有 onClick 行为。 普通的旧铯点基元没有 onClick 行为。 这可能是铯/镗的东西,也可能是反应的东西。

  • 尝试使用 PointPrimitiveCollection.add 添加已定义 onClick 方法的点。
  • 尝试使用 PointPrimitiveCollection.add() 添加点,然后添加一个 onClick 方法。
  • 尝试使用 PointPrimitiveCollection.add() 添加 JSX
  • 由于我的应用程序中的状态太大,我无法使用 useState 添加点 这是我尝试过的最小示例:
import { PointPrimitive, PointPrimitiveCollection, Viewer, useCesiumComponent } from 'resium';
import { Cartesian3, Color, PointPrimitiveCollection as PPC } from 'cesium';
import { useRef } from 'react';

const ingestStream = () => {
    const collectionRef = useRef(null);
    let pc: any;

    const addPoints = (pt) => {
        console.log('adding')
        if (pc === undefined) {
            if (collectionRef.current && collectionRef.current.cesiumElement) {
                pc = collectionRef.current.cesiumElement;
                globalThis.pointColl = pc;
                //TODO: add the else{} contents here when done editing them
            }
        } else {
            //adds point normally, ignores onClick
            pc.add({
                position: Cartesian3.fromDegrees(pt.LON, pt.LAT+2, pt.ALT_GEOM),
                color: { red: 1, green: 1, blue: 0, alpha: 1 },
                pixelSize: 60,
                onClick: () => {console.log('ow, clickage')},
            })
            
            //Adds onClick, but onClick does not fire with clicks
            const e = pc.add({
                position: Cartesian3.fromDegrees(pt.LON, pt.LAT, pt.ALT_GEOM),
                color: { red: 1, green: 1, blue: 0, alpha: 1 },
                pixelSize: 60,
                }
            );
            e.onClick = () => console.log('touched point')

            //adds point to (0,0,0) without onClick
            pc.add(JSXPoint_added)
            
        }
    };

    const ptconst = {
        LON: -80,
        LAT:43,
        ALT_GEOM: 100
    }

    const clickHandler = () => addPoints(ptconst)
    
    const JSXPoint_added = <PointPrimitive 
        position={ Cartesian3.fromDegrees(-77, 43, 100)} 
        color={Color.CYAN}
        pixelSize={30}
        onClick={clickHandler}
    />

    //onClick works, but there's no obvious reason when I inspect the PointPrimitiveCollection
    //or when I inspect PointPrimitiveCollection.get(0)
    const original = <PointPrimitive 
        position={ Cartesian3.fromDegrees(-75, 43, 100)} 
        color={Color.CYAN}
        pixelSize={30}
        onClick={clickHandler}
    />
    
    

    return (
        <Viewer
                id="resiumContainer"
                full
                baseLayerPicker={false}
                geocoder={false}
                animation={false}
                timeline={false}
                navigationInstructionsInitiallyVisible={false}
            >
            <PointPrimitiveCollection  ref={collectionRef}>
                {original}
            </PointPrimitiveCollection>

        </Viewer>

    );
};

export default ingestStream;

反应JS onClick OnClickListener 铯JS Resium

评论


答:

0赞 ResiumRegent 7/22/2023 #1

使用 ScreenSpaceEventHandler!

使用 resium 和 ceisum 导入之间有一点毛茸茸的,这个解决方案不是最佳代码,但它是解决这个问题的最佳技术。ScreenSpaceEventHandler 可以告诉您用户单击了 Cesium 画布上的哪个对象。如果被点击的对象具有唯一的 ID,则可以根据被点击的对象执行任意回调函数。下面是一个使用代码的示例

import { PointPrimitive, PointPrimitiveCollection, Viewer, useCesiumComponent } from 'resium';
import { Cartesian3, Color, PointPrimitiveCollection as PPC, ScreenSpaceEventHandler, ScreenSpaceEventType, defined as CesiumDefined} from 'cesium';
import { useEffect, useRef } from 'react';

const ingestStream = () => {
    const collectionRef = useRef(null);
    const viewRef = useRef(null);
    let pc: any;

    const addPoints = (pt) => {
        console.log('adding')
        if (pc === undefined) {
            if (collectionRef.current && collectionRef.current.cesiumElement) {
                pc = collectionRef.current.cesiumElement;
                globalThis.pointColl = pc;
                //TODO: add the else{} contents here when done editing them
            }
        } else {
            //adds point normally, ignores onClick
            pc.add({
                position: Cartesian3.fromDegrees(pt.LON, pt.LAT+2, pt.ALT_GEOM),
                color: { red: 1, green: 1, blue: 0, alpha: 1 },
                pixelSize: 60,
                onClick: () => {console.log('ow, clickage')},
                id: 'uniqueID'
            })
            
            //Adds onClick, but onClick does not fire with clicks
            const e = pc.add({
                position: Cartesian3.fromDegrees(pt.LON, pt.LAT, pt.ALT_GEOM),
                color: { red: 1, green: 1, blue: 0, alpha: 1 },
                pixelSize: 60,
                }
            );
            e.onClick = () => console.log('touched point')

            //adds point to (0,0,0) without onClick
            pc.add(JSXPoint_added)
            
        }
    };

    const ptconst = {
        LON: -80,
        LAT:43,
        ALT_GEOM: 100
    }

    const clickHandler = () => addPoints(ptconst)
    
    const JSXPoint_added = <PointPrimitive 
        position={ Cartesian3.fromDegrees(-77, 43, 100)} 
        color={Color.CYAN}
        pixelSize={30}
        onClick={clickHandler}
    />

    //onClick works, but there's no obvious reason when I inspect the PointPrimitiveCollection
    //or when I inspect PointPrimitiveCollection.get(0)
    const original = <PointPrimitive 
        position={ Cartesian3.fromDegrees(-75, 43, 100)} 
        color={Color.CYAN}
        pixelSize={30}
        onClick={clickHandler}
    />
    
    
    useEffect(() => {
        console.log('rendered')

    let handler;
    if (viewRef.current){
        console.log('making a listener')
        handler = new ScreenSpaceEventHandler(viewRef.current.cesiumElement.scene.canvas);
        handler.setInputAction(function(click) {
            const pickedObject = viewRef.current.cesiumElement.scene.pick(click.position);
            if (CesiumDefined(pickedObject) && pickedObject.id === 'uniqueID'){
                console.log(pickedObject.id)
            }
            console.log(pickedObject)
        }, ScreenSpaceEventType.LEFT_CLICK);
    
    }
    }, [
        //destroy the listener here
    ]); 
    
    
    

    return (
        <Viewer
                id="resiumContainer"
                full
                baseLayerPicker={false}
                geocoder={false}
                animation={false}
                timeline={false}
                navigationInstructionsInitiallyVisible={false}
                ref={viewRef}
            >
            <PointPrimitiveCollection  ref={collectionRef}>
                {original}
            </PointPrimitiveCollection>

        </Viewer>

    );
};

export default ingestStream;