Recreating the StateOfJS Survey Animation
Tags: react, javascript, gsap
Published: 2018-12-05 22:47:15

---
title: Recreating the StateOfJS Survey Animation
published: true
description: I set out to try and recreate the homepage from 2018's State of JS Survey page
tags: react, javascript, gsap
---

## The Task

If you follow the world of Javascript, chances are you came across the awesome new "State of Javascript 2018" survey. If not, you can check it out [here](https://2018.stateofjs.com/). I loved the animation at the beginning of it and set about trying to recreate it. Now I will walk through what I did.

My final product can be viewed [here](https://state-of-js-animation-rgd.herokuapp.com/). Not ready yet to be viewed on mobile.

### Caveat
I have never worked with Greensock inside of React before, so I'm sure this is a really sloppy and brute force way to approach the problem. I encourage other people to give it a go :)

### Project Overview
The example we are trying to emulate uses blocks to spell out "State of Javascript 2018" with a button to view the survey. I decided to spell out my name, "Ryan Dunton", and have a button that on hover, allows the user to view my actual name spelled out by the blocks.

I started by setting up an `App` component to hold my animating blocks. I give the `App` two state properties "home and margin". The home property will monitor if the elements should be at their starting position and the margin property will allow me to pass the margin property through as props and make it easier to calculate the animation container.

```javascript
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      home: false,
      margin: 20
    };
  }
```

Then I gave the `App` some `Letter` Components with props for setting up the initial animation

```javascript
        <Letter
            data="R"
            borderColor="red"
            isHome={this.state.home}
            animationType={"y"}
            currentLeftOrRight={"left"}
            currentTopOrBottom={"top"}
            margin={this.state.margin}
          />
```

I also add a `Button` component and pass it a function to change the `App`'s `this.state.home` to `true` on hover. 

(I'm using Styled Components so if this looks funky you can ignore it)

```javascript
       <ButtonWrapper>
          <EnterButton
            buttonText="Who am I?"
            checkForHover={this.checkForHover}
            removeHover={this.removeHover}
          />
        </ButtonWrapper>
```

Going into my Letter Component I need to find store MaxX, MaxY, MinX and MinY value because I am going to send each element to either the Max or Min of one of the axis and generate a random number within a range of the other. I decided to store this data in the Letter Component's state. I also wanted to monitor what "animationType" is being used, basically if it is moving to an X or Y max/min and the current side it is aligned with. I also needed to monitor if the animation was ended and the time/length of the animation. So the initial state of the Letter Component looks like this:

```javascript
      class Letter extends Component {
        constructor(props) {
        super(props);
        this.state = {
          x: 0,
          y: 0,
          animationTime: 2,
          minTop: 0,
          maxTop: 0,
          maxRight: 0,
          minLeft: 0,
          currentLeftOrRight: null,
          currentTopOrBottom: null,
          animationType: "",
          endAnimation: false
        };
```

I then need to set these value when the component mounts because I need to calculate its position on the screen. The most difficult part was figuring out the exact container dimensions. This is where passing the `margin` property through as a prop is helpful because I can reference it in the `ComponentDidMount` state calculations:

```javascript
this.setState({
      minTop: -offsetTop - margin,
      maxTop: windowHeight - elementHeight + margin - offsetTop,
      maxRight: windowWidth - elementX - (elementWidth - margin),
      minLeft: -offsetLeft - margin,
      animationType,
      currentLeftOrRight,
      currentTopOrBottom
    });
```

as well as passing it through to a Styled Component: 

```javascript
const StyledLetter = styled.div`
  margin: ${props => props.margin}px;
`;
```

So now I have a page that looks like the below with each `Letter` knowing all the information it needs to do for its animation.

![Alt text of image](https://s3.amazonaws.com/ryan-dunton-blogging-bucket/images/state-of-js-post1.png)

This is already way too long, so I'll end here and post a followup piece soon!