reearth / resium

React components for 🌏 Cesium
https://resium.reearth.io
MIT License
746 stars 135 forks source link

How to change entity's color when hovering #640

Open federicomarcantognini opened 1 year ago

federicomarcantognini commented 1 year ago

What I am looking for: cesium sandcastle

my current implementation:

Before the render()

const ref = React.useRef(null);

const test = e => {
  if (ref.current && ref.current.cesiumElement) {
    // ref.current.cesiumElement is Cesium's Viewer
    const picked = ref.current.cesiumElement.scene.pick(e.endPosition);
    const id = picked ? picked.id || picked.primitive.id : null;
    if (picked && id instanceof Cesium.Entity) {
      // picked is the picked entity
      const pickedElement = picked.id
      pickedElement.isSelected = true;
      pickedElement.originalColor = pickedElement.color;
      pickedElement._polyline._material._color._value = Cesium.Color.BLUE;
    }
  }
};

Inside the render()

<Resium.Viewer
  ref={ref}
>
  <Resium.ScreenSpaceEventHandler>
    <Resium.ScreenSpaceEvent action={(x) => test(x)} type={Cesium.ScreenSpaceEventType.MOUSE_MOVE} />
  </Resium.ScreenSpaceEventHandler>
</Resium.Viewer>

What am I missing? thanks in advance

sebastianstupak commented 6 months ago

Did you managed to figure this out?

I can't even trigger my ScreenSpaceEvents however I add them, whether it's creating new event handler and adding inputs, adding inputs on ref or through adding it via jsx.

My code:

"use client";

import React, { useEffect, useRef, useState } from "react";
import {
  CameraFlyTo,
  CesiumComponentRef,
  ImageryLayer,
  Viewer,
  ScreenSpaceEvent,
  ScreenSpaceEventHandler,
} from "resium";
import {
  Cesium3DTileset,
  Ion,
  Viewer as CesiumViewer,
  UrlTemplateImageryProvider,
  CesiumTerrainProvider,
  createWorldTerrainAsync,
  createOsmBuildingsAsync,
  ScreenSpaceEventType,
  KeyboardEventModifier,
} from "cesium";
import { highlights, initialView } from "./mapconfig";

Ion.defaultAccessToken = process.env.NEXT_PUBLIC_CESIUM_ACCESS_TOKEN as string;
const MAPBOX_ACCESS_TOKEN = process.env
  .NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN as string;

const mapbox = new UrlTemplateImageryProvider({
  url: `https://api.mapbox.com/styles/v1/mimo-mi/clwdr4pi600en01r0312n57op/tiles/512/{z}/{x}/{y}@2x?access_token=${MAPBOX_ACCESS_TOKEN}`,
});

const SolarMap = () => {
  const cesium = useRef<CesiumComponentRef<CesiumViewer>>(null);
  const [terrainProvider, setTerrainProvider] =
    useState<CesiumTerrainProvider>();
  const [tilesetProvider, setTilesetProvider] = useState<Cesium3DTileset>();

  useEffect(() => {
    const fetchTerrain = async () => {
      const terrain = await await createWorldTerrainAsync({
        requestVertexNormals: true,
      });
      setTerrainProvider(terrain);
    };
    const fetchOsmBuildings = async () => {
      const tileset = await createOsmBuildingsAsync();
      setTilesetProvider(tileset);
    };

    fetchTerrain();
    fetchOsmBuildings();
  }, []);

  useEffect(() => {
    const primitives = cesium?.current?.cesiumElement?.scene?.primitives;
    if (!primitives || !tilesetProvider) {
      return;
    }

    if (cesium.current?.cesiumElement?.scene.primitives.length! > 0) {
      return;
    }

    primitives.add(tilesetProvider);
  }, [cesium, tilesetProvider]);

  useEffect(() => {
    var cesiumElement = cesium?.current?.cesiumElement;
    if (!cesiumElement || !terrainProvider) {
      return;
    }

    if (cesiumElement.terrainProvider instanceof CesiumTerrainProvider) {
      return;
    }

    cesiumElement!.terrainProvider = terrainProvider;
  }, [cesium, terrainProvider]);

  return (
    <div className="h-full w-full relative">
      <Viewer
        ref={cesium}
        full
        timeline={false}
        animation={false}
        navigationHelpButton={false}
        fullscreenButton={false}
        shadows={false}
        baseLayerPicker={false}
        homeButton={false}
        vrButton={false}
        geocoder={false}
        sceneModePicker={false}
        selectionIndicator={false}
        navigationInstructionsInitiallyVisible={false}
      >
        <ScreenSpaceEventHandler>
          <ScreenSpaceEvent
            action={() => console.log("Left Click")}
            type={ScreenSpaceEventType.MOUSE_MOVE}
          />
          <ScreenSpaceEvent
            action={() => console.log("Right Click")}
            type={ScreenSpaceEventType.RIGHT_CLICK}
          />
          <ScreenSpaceEvent
            action={() => console.log("Left Double Click")}
            type={ScreenSpaceEventType.LEFT_DOUBLE_CLICK}
          />
          <ScreenSpaceEvent
            action={() => console.log("Shift + Right Click")}
            type={ScreenSpaceEventType.RIGHT_CLICK}
            modifier={KeyboardEventModifier.SHIFT}
          />
        </ScreenSpaceEventHandler>
        <CameraFlyTo
          duration={0}
          destination={initialView.position}
          orientation={{
            heading: initialView.heading,
            pitch: initialView.pitch,
            roll: initialView.roll,
          }}
        />
        <ImageryLayer imageryProvider={mapbox} />
      </Viewer>
    </div>
  );
};

export default SolarMap;

Neither of console logs work for me.

beaumcgee commented 5 months ago

Not specifically related to this issue, but thank you @sebastianstupak for providing a complete example of Resium using the "new" Cesium createWorldTerrainAsync functionality. I was having a hard time getting this working based on the other open issue #630.