I am applying perspective transformation to a react element, so the css property may look like this at one point:
transform: "perspective(48vh) rotateX(2deg) rotateY(3deg)"
I’m following the example here: https://armandocanals.com/posts/CSS-transform-rotating-a-3D-object-perspective-based-on-mouse-position.html, which is written in vanilla js
:
let constrain = 20;
let mouseOverContainer = document.getElementById("ex1");
let ex1Layer = document.getElementById("ex1-layer");
function transforms(x, y, el) {
let box = el.getBoundingClientRect();
let calcX = -(y - box.y - (box.height / 2)) / constrain;
let calcY = (x - box.x - (box.width / 2)) / constrain;
return "perspective(100px) "
+ " rotateX("+ calcX +"deg) "
+ " rotateY("+ calcY +"deg) ";
};
function transformElement(el, xyEl) {
el.style.transform = transforms.apply(null, xyEl);
}
mouseOverContainer.onmousemove = function(e) {
let xy = [e.clientX, e.clientY];
let position = xy.concat([ex1Layer]);
window.requestAnimationFrame(function(){
transformElement(ex1Layer, position);
});
};
The logic itself is trivial, but when re-writing it into react using hooks, I’m having some issue referencing the proper view, this answer nonewithstanding: react: element.getBoundingClientRect is not a function, and I’m having some issue in applying the animation. This is what I have so far:
const useStyles => makeStyles((theme: Theme) => createStyles({
container: {
height: `calc(100vh - 230px)`,
width: `calc(100vh-230px)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: `3.0px solid red`,
},
box : {
height: '48vh',
width: '48vh',
background: 'red',
borderRadius: '30px',
textAlign: 'center',
alignItems: 'center',
// eample: all perspective logic
transform: `perspective(48vh) rotateX(2deg) rotateY(3deg)`
}
}));
const useMousePosition = () => {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const setFromEvent = (e) => setPosition({ x: e.clientX, y: e.clientY });
window.addEventListener("mousemove", setFromEvent);
return () => {
window.removeEventListener("mousemove", setFromEvent);
};
}, []);
return position;
};
function goTransform({ pose, ref }){
// @TODO: implement this function
// based on `pose.x` `pose.y`, compute
// transform wrt. div's size
}
export default function PerspectiveContainer(props) {
const isOnMobile = useCheckMobileScreen(1000);
const classes = useStyles(isOnMobile)();
// persepctive shift
const pose = useMousePosition();
const inputRef = useRef();
// @TODO: impl. this function, then apply transformation
const transform = goTransform({ pose: pose, ref: inputRef })
return (
<Box className={classes.container}>
<Box ref={inputRef} className={classes.box}>
<h4 style={{color:'white'}}> { transform.x }, {transform.y } </h4>
</Box>
</Box>
)
}
I’m running into an issue where when I call ref.current
, the entire screen goes white, presumably because ref.current
is not a valid reference.