roelmore
roelmore

Reputation: 21

Animating Fireflies within Create-React-App Project

I am attempting to create a firefly background animation in my React portfolio that I am building as a learning project. I am leveraging the guidance provided here, but unfortunately the fireflies aren't "flying" -- they are just glowing in place. I am assuming it has something to do with how I've broken this code apart and implemented it within the Create-React-App structure.

Below are what I believe to be the relevant snippets from a stripped down code base where I've employed it.

I would greatly appreciate any thoughts you may have.

App.js

import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import { NavDropdown } from 'react-bootstrap';
import Banimation from './Banimation';




function App() {
  return (
    <div className="App">
      <header>
        <Navbar expand="lg" variant="dark" bg="dark">
          <Navbar.Brand href="#home">Roelmore Portfolio</Navbar.Brand>
            <Navbar.Toggle aria-controls="basic-navbar-nav" />
              <Navbar.Collapse id="basic-navbar-nav">
                <Nav className="mr-auto">
                  <Nav.Link href="#home">Home</Nav.Link>
                  <Nav.Link href="#link">Link</Nav.Link>
                  <NavDropdown title="Dropdown" id="basic-nav-dropdown">
                    <NavDropdown.Item>Action</NavDropdown.Item>
                    <NavDropdown.Item>Another Action</NavDropdown.Item>
                  </NavDropdown>
                </Nav>
              </Navbar.Collapse>
        </Navbar>
      </header>

    <div id="container">
        <Banimation total={25} />
    </div>
    </div>

  );
}

export default App;

Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';



ReactDOM.render(
    <App />,
    document.getElementById('root'),
    document.querySelector("#container")

);

Index.css

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #222222;
  overflow:hidden;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

.dot{
  width:4px;
  height:4px;
  position:absolute;
  background-color:#ff00cc;
  box-shadow:0px 0px 10px 2px #ff00cc;
  border-radius: 20px;
  z-index:2;
}

.fireflies {
  width: 100%;
  height: 100%;
}

Banimation.js:

import React from 'react';
import TweenLite from 'gsap';

const {
    useRef,
    useLayoutEffect,
  } = React

function R(max) {
    return Math.random() * max 
};

function Banimation(props) {
    const {
        total = 40 } = props
    
    const ref = useRef()

    useLayoutEffect(() => {
        const container = ref.current
        const w = window.innerWidth
        const h = window.innerHeight
        const dots = []

        function addAnimation(elm) {
            return TweenLite.to(elm, R(20) + 10, {
                bezier: {
                    values: [{
                        x: R(w),
                        y: R(h)
                    }, {
                    x: R(w),
                    y: R(h)
                    }]
                },
                opacity: R(1),
                scale: R(1) + 0.5,
                delay: R(2),
                onComplete: addAnimation,
                onCompleteParams: [elm]
            })
        }

        for (let i = 0; i < total; i++) {
            const div = document.createElement('div')
            TweenLite.set(div, {
                attr: {
                    class: 'dot'
                },
                x: R(w),
                y: R(h),
                opacity: 0,
            })
            container.appendChild(div);
            const dot = addAnimation(div)
            dot.play()
            dots.push(dot)
        }
        return () => {
            dots.forEach(dot=>dot.kill())
            container.innerHTML = ''
        }
    }, [total])
    return <div className="fireflies" ref={ref} />
    }
 
export default Banimation;

Upvotes: 1

Views: 321

Answers (1)

roelmore
roelmore

Reputation: 21

Team! I figured it out after a night of rest and a few more hours...

The code above uses the old "bezier" property from GSAP2, whereas I needed to use the "motionpath" property instead from the more current GSAP3.

Additionally, I had not imported and registered the MotionPathPlugin.

Thanks for letting me share this answer! Hopefully it helps some other newbie with what I imagine is a common question.

Upvotes: 1

Related Questions