How do I integrate a background JS animation into my react app?

三世轮回 提交于 2020-08-06 06:41:49

问题


I'm trying to add a firefly animation into a component within react (and the code I'm trying to use is here https://codepen.io/celli/pen/xZgpvN). If I had a simple HTML / CSS / Javascript setup I'd know what to do, but I'm confused on how to integration this animation in the context of React and in the scope of a single component. Where do I put the code below? How do I reference it within the component?


var total=40,
    container=document.getElementById('container'),
    w=window.innerWidth,
    h=window.innerHeight,
    Tweens=[],
    SPs=1;



for (var i=total;i--;){ 
    var Div=document.createElement('div');
    TweenLite.set(Div,{attr:{class:'dot'},x:R(w),y:R(h),opacity:0});
    container.appendChild(Div); Anim(Div);  Tweens.push(Div);
};

function Anim(elm){ 
    elm.Tween=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:Anim,onCompleteParams:[elm]})
};

for(var i=total;i--;){
  Tweens[i].Tween.play()};


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

Secondly, where do I put the CSS code below?

body{
  background-color: #222222;
  overflow:hidden;
}

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

#container {
width:100%; 
height:100%;
}

回答1:


React's page on Integrating With Other Libraries would probably be the best place to start.

Firstly, here's an example that can be run directly on StackOverflow.

const {
  useRef,
  useLayoutEffect,
} = React
// import React, { useRef, useLayoutEffect } from 'react';

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

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

  useLayoutEffect(() => {
    const contanier = 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 () => {
      // Clear animations and whatever here
      dots.forEach(dot=>dot.kill())
      container.innerHTML = ''
    }
  }, [total])
  return <div className="fireflies" ref={ref} />
}

function App() {
  return <Background total={25} / >
}

ReactDOM.render( <App / > , document.querySelector("#container"))
body {
  background-color: #222222;
  overflow: hidden;
}

.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%;
}
<div id="container" />

<!-- React -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<!-- TweenMax -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.15.0/TweenMax.min.js"></script>

Now the explanation.

A quick side note: the previously mentioned Integrating With Other Libraries page as of right now uses class components, but I like to use functional components because hooks are ₜₕₑ fᵤₜᵤᵣₑ. I also converted some of the code from old es5 to new modern es6 because modern js is ₜₕₑ fᵤₜᵤᵣₑ.

The basic idea is that when your component is first mounted, you run all the initial setup inside of a useLayoutEffect hook. That essentially boils down to throwing most of your current js inside of that hook.

The only thing the component needs to render is the div that will contain all of the dots.

The advantage here is that with react, you get to control aspects of your animation with props--demonstrated in the example by allowing the total variable to be passed as a prop.

Also, since React provides a way to get a reference to a dom node via the useRef hook, you can use that instead of document.querySelector('#contanier').

Where do I put the CSS

The best place really depends on how you set up your react application.

If you have an HTML template somewhere, you can just throw a style tag or a link tag in there as you would any other project.

If you used create-react-app or have a similar setup then you might just import them into your component by importing the stylesheet, by using css modules, or by modifying src/index.css.

Another option is to use css-in-js solutions such as emotion or styled-components but those will probably take a little getting used to.



来源:https://stackoverflow.com/questions/58574393/how-do-i-integrate-a-background-js-animation-into-my-react-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!