Skip to content

Commit

Permalink
Added flip animation for flip card & boomerang animation on the close…
Browse files Browse the repository at this point in the history
…d console
  • Loading branch information
JowaDev committed Jun 23, 2024
1 parent 906090c commit 08e8f5b
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 111 deletions.
Binary file modified bun.lockb
Binary file not shown.
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,29 @@
"lint": "next lint"
},
"dependencies": {
"@react-three/fiber": "^8.16.3",
"@react-three/fiber": "^8.16.8",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"framer-motion": "^11.1.8",
"framer-motion-3d": "^11.1.8",
"framer-motion": "^11.2.11",
"framer-motion-3d": "^11.2.11",
"lucide-react": "^0.378.0",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
"next": "^14.2.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-resizable-panels": "^2.0.19",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
"three": "^0.164.1",
"use-sound": "^4.0.1"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"@types/node": "^20.14.8",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.3",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.5.2"
}
}
183 changes: 86 additions & 97 deletions src/components/Card/CardFan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,129 +12,118 @@ interface CardFanProps {
export const CardFan: FC<CardFanProps> = () => {
const {isWindowReduced} = useContext(globalContext);
const {cards} = useRotateCards([
{
id: 0,
title: "2015",
description: "Description 1",
rotate: 0
},
{
id: 1,
title: "2016",
description: "Description 2",
rotate: 0
},
{
id: 2,
title: "2018",
description: "Description 3",
rotate: 0
},
{
id: 3,
title: "2020",
description: "Description 4",
rotate: 0
},
{
id: 4,
title: "2022",
description: "Description 5",
rotate: 0
},
{
id: 5,
title: "2024",
description: "Description 6",
rotate: 0
}
{id: 0, title: "2015", description: "Description 1", rotate: 0},
{id: 1, title: "2016", description: "Description 2", rotate: 0},
{id: 2, title: "2018", description: "Description 3", rotate: 0},
{id: 3, title: "2020", description: "Description 4", rotate: 0},
{id: 4, title: "2022", description: "Description 5", rotate: 0},
{id: 5, title: "2024", description: "Description 6", rotate: 0}
]);

const [clickedCard, setClickedCard] = useState<number | null>(null);

return (
<motion.div
initial={{
opacity: 0
}}
animate={{
opacity: isWindowReduced && 1 || 0
}}
exit={{
opacity: 0,
}}
transition={{
opacity: {
duration: .33
}
}}
initial={{opacity: 0}}
animate={{opacity: isWindowReduced ? 1 : 0}}
exit={{opacity: 0}}
transition={{opacity: {duration: 0.33}}}
>
<Spotlight/>
<Spotlight
fill='white'
/>
<div
className={`${isWindowReduced ? 'flex' : 'hidden'} fixed top-1/4 left-1/2 transform -translate-y-1/4 -translate-x-1/2 z-[1]`}
>
{
cards.map(({id, title, description, rotate}) => (
<Card
key={id}
title={title}
description={description}
rotate={rotate}
/>
))
}
className={`${isWindowReduced ? 'flex' : 'hidden'} fixed top-1/4 left-1/2 transform -translate-y-1/4 -translate-x-1/2 z-[1]`}>
{cards.map(({id, title, description, rotate}) => (
<Card
key={id}
id={id}
title={title}
description={description}
rotate={rotate}
isClicked={clickedCard === id}
onClick={() => setClickedCard(id)}
/>
))}
</div>
</motion.div>
);
};

interface CardProps {
id: number;
title: string;
description: string;
rotate: number;
isClicked: boolean;
onClick: () => void;
}

const Card: FC<CardProps> = ({title, description, rotate}) => {
const Card: FC<CardProps> = ({id, title, description, rotate, isClicked, onClick}) => {
const {isWindowReduced} = useContext(globalContext);
const [cardIsOverlapped, setCardIsOverlapped] = useState(false);

return (
<motion.div
className={`fixed bg-console h-[450px] w-[250px] rounded-lg p-4 border border-${cardIsOverlapped ? 'secondary' : 'primary'} origin-bottom-left overflow-hidden`}
onMouseOver={() => {
setCardIsOverlapped(true);
}}
onMouseOut={() => {
setCardIsOverlapped(false);
}}
initial={{
rotate: 0
}}
onMouseOver={() => setCardIsOverlapped(true)}
onMouseOut={() => setCardIsOverlapped(false)}
onClick={onClick}
initial={{rotateY: 0}}
animate={{
rotate: isWindowReduced ? rotate : 0,
y: cardIsOverlapped && -50 || 0
rotateY: isClicked ? 180 : 0,
y: cardIsOverlapped ? -50 : 0
}}
transition={{
rotate: {
duration: isWindowReduced ? 1 : .33
},
y: {
duration: .33
}
}}
exit={{
rotate: isWindowReduced ? rotate : 0,
}}
style={{
zIndex: cardIsOverlapped && 1 || 0
rotate: {duration: isWindowReduced ? 1 : 0.33},
rotateY: {duration: 0.5},
y: {duration: 0.33}
}}
exit={{rotate: isWindowReduced ? rotate : 0}}
style={{zIndex: cardIsOverlapped ? 1 : 0}}
>
<h2>
{title}
</h2>
<p>
{description}
</p>
<span
className="fixed -bottom-10 -left-8 bg-secondary h-16 w-12 transform rotate-45 animate-pulse"
/>
<h2>{title}</h2>
<p>{description}</p>
<span className="fixed -bottom-10 -left-8 bg-secondary h-16 w-12 transform rotate-45 animate-pulse"/>
</motion.div>
)
;
);
};

const pathData = "M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80";

interface AnimatedLineProps {
}

export const AnimatedLine: FC<AnimatedLineProps> = () => {
return (
<svg
className='fixed z-50 top-0'
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg"
style={{width: "100%", height: "100vh", background: "transparent"}}
>
<motion.path
d={pathData}
fill="red"
stroke="red"
strokeWidth="4"
strokeDasharray="0 1"
animate={{
pathLength: [0, 1],
strokeDasharray: ["0, 1", "1, 0"],
rotate: [0, 200],
rotateY: [0, 180],
rotateX: [0, 260],
scale: [0, 1],
}}
transition={{
duration: 4,
ease: "anticipate",
repeat: Infinity,
repeatType: "reverse"
}}
/>
</svg>
);
};
2 changes: 1 addition & 1 deletion src/components/Console/Console.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface FadeInProps {

export const Console: FC<FadeInProps> = ({children}) => {
const {isWindowReduced, setIsWindowReduced, isConsoleClosed} = useContext(globalContext);
useCloseConsole(5000);
useCloseConsole(8000);
return (
<motion.div
className={`absolute inset-0 bg-[#09090b] rounded-lg border border-primary overflow-hidden h-full w-full ${isWindowReduced && "cursor-pointer"}`}
Expand Down
6 changes: 6 additions & 0 deletions src/components/Console/ConsoleBackground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import {FC, ReactNode, useContext} from "react";
import {motion} from "framer-motion";
import {globalContext} from "@/components/Layout/GlobalContext";
import {AnimatedLine} from "@/components/Card/CardFan";

interface ConsoleBackgroundProps {
children: ReactNode;
Expand All @@ -25,6 +26,11 @@ export const ConsoleBackground: FC<ConsoleBackgroundProps> = ({children}) => {
}}
transition={{type: "spring", duration: 1, bounce: .5}}
>
{
isConsoleClosed && (
<AnimatedLine/>
)
}
{children}
</motion.div>
</>
Expand Down

0 comments on commit 08e8f5b

Please sign in to comment.