loading...

Recreating the StateOfJS Survey Animation Part 2

ryan_dunton profile image Ryan Dunton ・2 min read

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:

components

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.

go home

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!

Posted on by:

ryan_dunton profile

Ryan Dunton

@ryan_dunton

Frontend Developer, more JS = more fun (?)

Discussion

markdown guide