React

by mamounothman

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0-alpha.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0-alpha.2/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/MotionPathPlugin.js"></script>
<div id="app"></div>

CSS

.wrap{
  position: relative;
  width: 375px;
  height: 480px;
  background: #e9e9e9;
  border-radius: 5px;
}

.bubble{
   position: absolute;
   left: 50%;
   bottom: 0;
   width: 32px;
   height: 32px;
   border-radius: 50%;
   background: #f0f;
   font-size: 12px;
   color: #fff;
   overflow: hidden;
   text-align: center;
}

Babel + JSX

const { useState, useEffect, useRef } = React;

gsap.registerPlugin(MotionPathPlugin)

const Bubble = ({ onClose, data }) => {
	const pointRef = useRef(null)
	useEffect(() => {
    const path = []
    let offsetY = 0
    for(let i = 0; i < 10; i++) {
      const y = offsetY - Math.floor(Math.random() * 20 + 30)
      offsetY = y
      path.push({ x: Math.floor(Math.random() * 40 - 20), y })
    }
    gsap.to(pointRef.current, 5, {
      motionPath: {
        path,
        type: 'cubic'
      },
      onComplete: () => onClose()
    })
    return () => {}
  }, [])
	return (<span className="bubble" ref={pointRef}>{data.id}</span>)
}

const App = () => {
	const [count, setCount] = useState(0)
  const [bubbles, setBubbles] = useState([])

	const handleCreate = () => {
  	setBubbles([...bubbles, {id: count}])
    setCount(count + 1)
  }
  
  const handleClose = index => {
  	const newBubbles = [...bubbles]
    newBubbles.splice(index, 1)
    setBubbles(newBubbles)
  }
  
  return (
    <div className="wrap">
      {
      	bubbles.map((item, index) => (
        	<Bubble
            key={item.id}
            data={item}
            onClose={() => handleClose(index)} />
        ))
      }
      <button type="button" onClick={handleCreate}>Click Me</button>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))