This is part 2 of my attempt to recreate the 2018 State of JS Animation. Part 1 can be found here
A look at my finished attempt.
When we left off I had a page that looked like this:
And each Letter
component has the following state which runs on mount
this.setState({
minTop: -offsetTop - margin,
maxTop: windowHeight - elementHeight + margin - offsetTop,
maxRight: windowWidth - elementX - (elementWidth - margin),
minLeft: -offsetLeft - margin,
animationType,
currentLeftOrRight,
currentTopOrBottom
});
Now that each component knows its minTop, maxTop, maxRight, minLeft and the animationType we can make the animation function.
Since we are using GreenSock's TweenLite we can move to a new x,y coordinate, we just have to get the coordinates. We can get the coordinates with a simple switch statement and give it random opposite coordinates within the max/min range.
const getNewCoordinates = (minTop, maxTop, minLeft, maxRight, currentSide) => {
let xDirection, yDirection, x, y;
// alternate sides
switch (currentSide) {
case "left":
xDirection = "right";
x = maxRight;
y = Math.random() * maxTop + minTop;
break;
case "right":
xDirection = "left";
x = minLeft;
y = Math.random() * maxTop + minTop;
break;
case "top":
yDirection = "bottom";
x = Math.random() * minLeft + maxRight;
y = minTop;
break;
case "bottom":
yDirection = "top";
x = Math.random() * minLeft + maxRight;
y = maxTop;
break;
default:
break;
}
return { x, y, xDirection, yDirection };
};
So now we pass that information to a tween animation that updates state but and viola! We have letters moving around the screen and call a flipAnimation
function that just changes the animationType
from "x" to "y" and refires the animation at the end of each animation.
moveAnimation = () => {
this.animation = TweenLite.to(
this.letterElement,
this.state.animationTime,
{
x: this.state.x,
y: this.state.y,
ease: Linear.easeNone,
onComplete: this.flipAnimation
}
);
};
So now we have letters moving around the screen, all we need to do is get them to "go home" on hover.
We know from Greensock that the 'home' location is x:0,y:0
. So we call a function when the App
home state is set to true that moves all the Letters
to 0,0 and give it a faster animationTime
for a cool little effect.
returnToHome = () => {
if (this.state.x !== 0) {
this.setState({
x: 0,
y: 0,
animationTime: 0.5,
endAnimation: true
});
}
};
The only tricky part left is "restarting" the animations on end of hover. We can check if our this.props.isHome
equals false and the this.state.endAnimation
equals true. Which means the user is no longer hovering but the component is not animating yet, so we call the animation.
if (!this.props.isHome && this.state.endAnimation) {
this.setState({
endAnimation: false
});
this.flipAnimation();
}
Boom! Now we have a passable prototype. I still need to add resize functions and some mobile compatibility but other than that it is ready for the world.
Obviously I blew through some steps but the full code can be found on Github.
Integrating React and Greensock was suprisingly easy and I hope to do it again!
Top comments (0)