Add onClick event in sphere using react-babylonjs?

I am using react-babylonjs to make sphere, I want when user click on sphere it should run function that I created. I can not find example of using action manager in sphere component. Please help.

Invoking our React master @brianzinn

You can do it with action manager no problem. First would be a general way using the scene picking (without action manager) and may suit your needs for a mostly static scene:

const onMeshPicked = (pickedMesh) => {
  if (pickedMesh.name === 'sphere1') {
    pickedMesh.scaling.y += 0.1;
  }
}

<Engine ...>
      <Scene onMeshPicked={onMeshPicked}>
         ...
         <sphere name='sphere1' ... />
      </Scene>
</Engine>

One way to use an action manager via a hook (useClick is part of react-babylonjs is like this:

const getRandomColor = (function () {
  // const Colors = ['#4F86EC', '#D9503F', '#F2BD42', '#58A55C'];
  const Colors = [[0.31, 0.53, 0.93, 1], [0.85, 0.31, 0.25, 1], [0.95, 0.74, 0.26, 1], [0.35, 0.65, 0.36, 1]];

  let i = 0;
  return () => {
    i++;
    return Colors[i % Colors.length];
  }
})();

const initialColor = Color3.FromArray(getRandomColor());

function WithUseClick() {
  const [color, setColor] = useState(initialColor);
  const [ref] = useClick(_ => {
    const color = getRandomColor();
    setColor(Color3.FromArray(color))
  });

  return <sphere name='sphere1' ref={ref}
                 diameter={2} segments={32}
                 position={new Vector3(0, 1, 0)}>
    <standardMaterial  name='mat' diffuseColor={color}/>
  </sphere>
}

export const MyScene = () => (
    <Engine antialias adaptToDeviceRatio canvasId='babylonJS'>
      <Scene>
        <freeCamera name='camera1' position={new Vector3(0, 5, -10)} setTarget={[Vector3.Zero()]}/>
        <hemisphericLight name='light1' intensity={0.7} direction={Vector3.Up()}/>
        <WithUseClick/>
        <ground name='ground1' width={6} height={6} subdivisions={2}/>
      </Scene>
    </Engine>
);

Now every time you click the sphere it will cycle through those “random” colors. The source for the useClick is here react-babylonjs/hooks.ts at master · brianzinn/react-babylonjs · GitHub
You could inline that hook to your code or connect to a useRef hook as well. Note that the ref works as well like it does on regular host elements you are used to (like div).

For completeness you can also register with Mesh events with onCreated / onDispose. I think you’ll want to clean up with onDispose (actually looking at the hook it is missing a cleanup in the useEffect :slight_smile: )

const onSphereCreated = (sphere) => {
  sphere.actionManager = new ActionManager(sphere.getScene());
  sphere.actionManager.registerAction(
    new ExecuteCodeAction(
      ActionManager.OnPickTrigger, function (ev) {
        console.log('sphere clicked', ev);
      }
    )
  );
}

export const ClickableSphere = () => (
    <Engine ... >
      <Scene>
        ...
        <sphere ... onCreated={onSphereCreated} />
      </Scene>
    </Engine>
)

There are other ways as well as there are a lot of extension points, but those ways are all good. Cheers.

@brianzinn thank you so much, So I tried register with Mesh events with onCreated because it was easy to understand as I have used action manger before. I have small glitch, I can not click on some of sphere, I need to move/rotate it little bit and then I get the option to click. what you thing should I use onDispose to solve this problem?

For the onDispose you could just unregister the action. Let’s try to find out why you can’t click on some of the sphere. Does this example have the same issue?
https://brianzinn.github.io/react-babylonjs/?path=/story/hooks--use-click-event

I think you’ll need to share some code - engine and scene creation specifically to start - is it just by pixels or not working until you rotate?

Oh got it, sorry for very late response but I get it working. Thank you so much for you help.

1 Like