I am brand new into the programming world. I am trying to create a circle that follows the mouse around in Three JS. Here is my code. The circle follows the mouse, but visually it is about half screen width and height away from actual cursor position. How can I fix it?
const CircleFollowMouse = () => {
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
const circleSize = 40; // Define the size of the circle
useEffect(() => {
const handleMouseMove = (event) => {
// Update mouse position state with the current mouse position
setMousePosition({ x: event.pageX, y: event.pageY });
};
// Add mouse move event listener
document.addEventListener('mousemove', handleMouseMove);
// Remove event listener on cleanup
return () => {
document.removeEventListener('mousemove', handleMouseMove);
};
}, []);
return (
<Html>
<div
className="circle"
style={{
left: `${mousePosition.x - circleSize / 2}px`, // Center the circle on the mouse by adjusting for half its size
top: `${mousePosition.y - circleSize / 2}px`, // Center the circle on the mouse by adjusting for half its size
width: `${circleSize}px`, // Set the width of the circle
height: `${circleSize}px`, // Set the height of the circle
borderRadius: '50%', // Make the div a circle
backgroundColor: 'white', // Set the circle color
position: 'fixed', // Ensure the circle follows the mouse correctly
zIndex: 9999, // Make sure the circle is above other content
}}
></div>
</Html>
);
};
By default Html
from @react-three/drei
is centered on the middle of the screen.
You have two options here:
Html
layout to put it back into top-left corner:<Html
style={{
transform: `translate3d(-50vw, -50vh, 0)`
}}
></Html>
{
left: `${mousePosition.x - circleSize / 2 - halfScreenWidth}px`,
top: `${mousePosition.y - circleSize / 2 - halfScreenHeight}px`
}
Alternatively, IMO, instead of previous implementation, a more "good process" integration would be to use useFrame
and state.pointer
instead of useEffect
and addEventListener.mousemove
:
import { useFrame, useThree } from '@react-three/fiber'
const { size } = useThree()
useFrame((state) => {
setMousePosition({
// state.pointer.xy are values from -1.0 to 1.0 so they match the logic of the anchor of Html being anchored in the middle
x: state.pointer.x * (size.width * 0.5),
y: state.pointer.y * (size.height * -0.5)
})
})
// also apply pointerEvents: none to your circle.