4

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>
  );
};

1 Answer 1

4

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.