Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent click through objects in React-Fiber Three.js

Here is a cube of planes that I can click

The main issue with this so far is that clicking on a plane clicks through when I would only want to click the plane that my mouse is over. What am I missing on my Three.js Plane?

I have tried searching for something relating to collision in three.js but to no avail so far.

After further research, I think it has something to do with RayCasting?

import React, { useState, useRef } from "react";
import { OrbitControls, Plane } from "@react-three/drei";
import { Canvas, useFrame, useThree, extend } from "@react-three/fiber";
import styles from "../styles/game.module.css";
import { DoubleSide } from "three";

const Cell = (props) => {
  const [hovered, hover] = useState(false);
  const [checked, setChecked] = useState(false);

  const colorStyle = () => {
    if (hovered) return "hotpink";
    if (checked) return "lightblue";
    return "orange";
  };
  return (
    <Plane
      scale={1}
      onClick={() => setChecked(!checked)}
      onPointerEnter={() => hover(true)}
      onPointerLeave={() => hover(false)}
      position={props.position}
      rotation={props.rotation}
    >
      <meshPhongMaterial side={DoubleSide} color={colorStyle()} />
    </Plane>
  );
};

const Cube = () => {
  useFrame((state, delta) => {
  });

  return (
    <>
      {/* Back Face */}
      <Cell position={[-1, 1, -1.5]} rotation={[0, 0, 0]} />
      // other cells here

      {/* Front Face */}
      <Cell position={[-1, 1, 1.5]} rotation={[0, 0, 0]} />
      // other cells here

      {/* Left Face */}
      <Cell position={[-1.5, 1, 1]} rotation={[0, Math.PI / 2, 0]} />
      // other cells here

      {/* Right Face */}
      <Cell position={[1.5, 1, 1]} rotation={[0, Math.PI / 2, 0]} />
      // other cells here
      
      {/* Bottom Face */}
      <Cell position={[1, -1.5, 1]} rotation={[Math.PI / 2, 0, 0]} />
      // other cells here
      
      {/* Top */}
      <Cell position={[1, 1.5, 1]} rotation={[Math.PI / 2, 0, 0]} />
     // other cells here
    </>
  );
};

const SceneItems = () => {
  return (
    <>
      <OrbitControls minDistance={7.5} maxDistance={15} />
      <ambientLight intensity={0.5} />
      <spotLight position={[10, 15, 10]} angle={0.3} />
      <Cube position={[1, 1, 1]} />
    </>
  );
};

const CompleteScene = () => {
  return (
    <div id={styles.scene}>
      <Canvas>
        <SceneItems />
      </Canvas>
    </div>
  );
};
like image 829
pythonNovice Avatar asked Oct 15 '25 08:10

pythonNovice


1 Answers

It appears that all I needed to prevent this click-through from happening was to add event.stopPropagation() to my event listeners on my Plane. Now I no longer click through the Plane


const Cell = (props) => {
  const [hovered, hover] = useState(false);
  const [checked, setChecked] = useState(false);

  useCursor(hovered);

  const colorStyle = () => {
    if (hovered) return "hotpink";
    if (checked) return "lightblue";
    return "orange";
  };
  return (
    <Plane
      scale={1}
      onClick={(e) => {
        e.stopPropagation();
        setChecked(!checked);
      }}
      onPointerEnter={(e) => {
        e.stopPropagation();
        hover(true);
      }}
      onPointerLeave={(e) => {
        e.stopPropagation();
        hover(false);
      }}
      position={props.position}
      rotation={props.rotation}
    >
      <meshPhongMaterial side={DoubleSide} color={colorStyle()} />
    </Plane>
  );
};

More details here: https://docs.pmnd.rs/react-three-fiber/api/events#pointer-capture

like image 188
pythonNovice Avatar answered Oct 16 '25 21:10

pythonNovice



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!