From 93eb451880446de237992512520172962c501a29 Mon Sep 17 00:00:00 2001 From: Alvalen Date: Mon, 1 Jul 2024 15:41:21 +0700 Subject: [PATCH] feat: add animate quote at about page --- app/(root)/page.jsx | 7 ++- app/about/(quote)/quote.jsx | 63 ++++++++++++++++++++ app/about/(quote)/style.css | 45 ++++++++++++++ app/about/(quote)/useIntersectionObserver.js | 32 ++++++++++ app/about/page.jsx | 21 +++++++ 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 app/about/(quote)/quote.jsx create mode 100644 app/about/(quote)/style.css create mode 100644 app/about/(quote)/useIntersectionObserver.js diff --git a/app/(root)/page.jsx b/app/(root)/page.jsx index 8280b94..7bd6cc6 100644 --- a/app/(root)/page.jsx +++ b/app/(root)/page.jsx @@ -100,7 +100,12 @@ const MyPage = () => { type: "spring", }}> diff --git a/app/about/(quote)/quote.jsx b/app/about/(quote)/quote.jsx new file mode 100644 index 0000000..8b53c35 --- /dev/null +++ b/app/about/(quote)/quote.jsx @@ -0,0 +1,63 @@ +// Quote.js +import "./style.css"; +import { motion } from "framer-motion"; +import { useIntersectionObserver } from "./useIntersectionObserver"; + +export default function Quote() { + const text1 = '"There are no limits to what you can accomplish'.split(" "); + const text2 = 'except the limits you place on your own thinking."'.split( + " " + ); + const [ref, isIntersecting] = useIntersectionObserver(); + + return ( +
+

+ {text1.map((word, index) => ( + + {word}{" "} + + ))} +

+

+ {text2.map((word, index) => ( + + {word}{" "} + + ))} +

+
+ ); +} diff --git a/app/about/(quote)/style.css b/app/about/(quote)/style.css new file mode 100644 index 0000000..9532051 --- /dev/null +++ b/app/about/(quote)/style.css @@ -0,0 +1,45 @@ +@keyframes scale { + 100% { + transform: scale(1); + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + } +} + +@keyframes fade-in { + 100% { + opacity: 1; + filter: blur(0); + -webkit-filter: blur(0); + } +} + +.q-wrap { + display: inline-block; + opacity: 1; + filter: blur(4px); + -webkit-filter: blur(4px); +} + +.q-wrap:nth-child(1) { + animation: fade-in 0.8s 0.1 forwards cubic-bezier(0.11, 0, 0.5, 0); + -webkit-animation: fade-in 0.8s 0.1 forwards cubic-bezier(0.11, 0, 0.5, 0); +} + +.q-wrap:nth-child(2) { + animation: fade-in 0.8s 0.2 forwards cubic-bezier(0.11, 0, 0.5, 0); + -webkit-animation: fade-in 0.8s 0.2 forwards cubic-bezier(0.11, 0, 0.5, 0); +} + +.q { + text-align: center; + transform: scale(0.92); + -webkit-transform: scale(0.92); + -moz-transform: scale(0.92); + -ms-transform: scale(0.92); + -o-transform: scale(0.92); + animation: scale 3s forwards cubic-bezier(0.5, 1, 0.89, 1); + -webkit-animation: scale 3s forwards cubic-bezier(0.5, 1, 0.89, 1); +} \ No newline at end of file diff --git a/app/about/(quote)/useIntersectionObserver.js b/app/about/(quote)/useIntersectionObserver.js new file mode 100644 index 0000000..8ffdd9b --- /dev/null +++ b/app/about/(quote)/useIntersectionObserver.js @@ -0,0 +1,32 @@ +// useIntersectionObserver.js +import { useEffect, useState, useRef } from "react"; + +export function useIntersectionObserver() { + const [isIntersecting, setIsIntersecting] = useState(false); + const ref = useRef(null); + + useEffect(() => { + const observer = new IntersectionObserver( + ([entry]) => { + setIsIntersecting(entry.isIntersecting); + }, + { + root: null, + rootMargin: "0px", + threshold: 0.1, + } + ); + + if (ref.current) { + observer.observe(ref.current); + } + + return () => { + if (ref.current) { + observer.unobserve(ref.current); + } + }; + }, []); + + return [ref, isIntersecting]; +} diff --git a/app/about/page.jsx b/app/about/page.jsx index 5ab119e..fdd777d 100644 --- a/app/about/page.jsx +++ b/app/about/page.jsx @@ -8,6 +8,7 @@ import FixedButon from "@/components/FixedButton"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChevronLeft } from "@fortawesome/free-solid-svg-icons"; import Card from "./(spotify)/card.jsx"; +import Quote from "./(quote)/quote.jsx"; // images import Me1 from "@/public/img/me1.jpg"; @@ -453,6 +454,26 @@ export default function Page() {

+ +
+ + + +
);