From 7d1d01d17b41b8664451e95ea312043a52d99906 Mon Sep 17 00:00:00 2001 From: Aaron Chan <42254254+aaronchan32@users.noreply.github.com> Date: Sun, 7 Apr 2024 16:42:43 -0700 Subject: [PATCH] feat: add floating animation after initial asteroid movement --- src/components/Asteroid/Asteroid.tsx | 46 ++++++++++++++++++++---- src/components/Asteroid/asteroidLogic.ts | 12 ++----- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/components/Asteroid/Asteroid.tsx b/src/components/Asteroid/Asteroid.tsx index 1aa3be9..9483a4a 100644 --- a/src/components/Asteroid/Asteroid.tsx +++ b/src/components/Asteroid/Asteroid.tsx @@ -1,4 +1,4 @@ -import { motion } from 'framer-motion'; +import { Transition, motion } from 'framer-motion'; import React, { useEffect, useRef } from 'react'; import { useState } from 'react'; @@ -14,10 +14,10 @@ type AsteroidProps = { homeRef: React.RefObject; }; -type animationProps = { +export type animationProps = { initial: Point; - animate: Point; - transition: { duration: number; ease: number[] }; + animate: EndPoint; + transition: Transition; }; export type Point = { @@ -25,6 +25,10 @@ export type Point = { y: number; }; +type EndPoint = Point & { + rotate: number; +}; + export default function Asteroid({ homeRef }: AsteroidProps) { const [asteroidAnimations, setAsteroidAnimations] = useState< animationProps[] @@ -100,7 +104,7 @@ export default function Asteroid({ homeRef }: AsteroidProps) { } }, [homeRef, numAsteroids]); - const clickMeLocation = { x: window.innerWidth / 3, y: 100 }; + const clickMeLocation = { x: window.innerWidth / 3 - 50, y: 100 }; const FragmentAsteroidComponents = [ FragmentAsteroid1, @@ -123,9 +127,36 @@ export default function Asteroid({ homeRef }: AsteroidProps) { ); const asteroidScales = useRef( - Array.from({ length: numAsteroids }, () => Math.random() * 0.7 + 0.6) + Array.from({ length: numAsteroids }, () => Math.random() * 0.6 + 0.7) ).current; + const beginFloatAnimation = (index: number) => { + const asteroidElement = asteroidRefs.current[index]?.current; + if (asteroidElement) { + setAsteroidAnimations(allPrevAnimations => { + const newAnimations = [...allPrevAnimations]; + const previousAnimation = newAnimations[index]; + const { y, rotate } = previousAnimation.animate; + const rotateLeft = Math.random() > 0.5; + newAnimations[index] = { + ...previousAnimation, + animate: { + ...previousAnimation.animate, + y: y + 12, + rotate: rotateLeft ? rotate + 10 : rotate - 10 + }, + transition: { + duration: 3.5, + repeat: Infinity, + repeatType: 'reverse', + ease: 'easeInOut' + } + }; + return newAnimations; + }); + } + }; + return (
{asteroidScales.map((scale, index) => @@ -167,6 +198,9 @@ export default function Asteroid({ homeRef }: AsteroidProps) { transition={asteroidAnimations[index]?.transition} ref={asteroidRefs.current[index]} style={{ scale: index === 0 ? 1 : scale }} + onAnimationComplete={() => { + beginFloatAnimation(index); + }} > {index === 0 &&

Click Me !

} diff --git a/src/components/Asteroid/asteroidLogic.ts b/src/components/Asteroid/asteroidLogic.ts index 7c250e8..f4baebd 100644 --- a/src/components/Asteroid/asteroidLogic.ts +++ b/src/components/Asteroid/asteroidLogic.ts @@ -1,5 +1,5 @@ import React from 'react'; -import { Point } from './Asteroid'; +import { Point, animationProps } from './Asteroid'; //prettier-ignore type AsteroidProps = { @@ -8,7 +8,7 @@ type AsteroidProps = { contentPaddingRight: number; contentWidth: number; setAsteroidVisibility: React.Dispatch>; - setAsteroidAnimations: React.Dispatch>; + setAsteroidAnimations: React.Dispatch>; setFragmentEndPts: React.Dispatch>; }; @@ -22,15 +22,7 @@ export default function asteroidLogic({ }: AsteroidProps) { setAsteroidVisibility(Array(numAsteroids).fill(true)); - //Startpt x: -window.innerWidth < x < 0 - //Startpt y: 0 < y < window.innerHeight const generateStartPT = () => { - // const startPT = { - // x: -((Math.random() * window.innerWidth) / 4), - // y: Math.random() * window.innerHeight - // }; - // return startPT; - // Randomly decide whether to place the point offscreen to the left or the bottom const isLeft = Math.random() > 0.5;