След като успешно обсъдихме използването на View Transitions API с Vanilla JavaScript и след това с ReactJS, за анимиране на преходи между различни маршрути (или изгледи) на нашето приложение, ще преминем стъпка по стъпка в нов урок със същата тема , Но сега ще използваме NextJS 13 с новата структура на App Router, Всичко това, използвайки само CSS, не са необходими допълнителни библиотеки на трети страни.
Съдържание
- Какво представлява API за преглед на преходи
- Дали View Transition API е широко възприет от съвременните браузъри?
- Преди да преминете към този урок
- Какво строим?
- Да кодираме
- Пълен изходен код
Какво представлява API за преглед на преходи
API за преглед на преходи предоставя начин за създаване на анимиран преход между два документа (изгледи), без да създавате припокриване в прехода.
View Transitions правят този процес лесен и пълен, като ви позволяват да направите своя DOM промяна без никакво припокриване между състоянията, като създадете анимация за преход между състоянията с помощта на моментални изгледи.
Текущата реализация на този API е насочена към приложения с една страница (SPA). В този урок ще обясним как да направите това с помощта на NextJS 13 с новата папка App.
Прочетете повече за View Transitions API тук.
Прегледът на преходите API широко ли е възприет от съвременните браузъри?
По времето, когато се пише тази статия, View Transitions API е възприет от Chrome (v 111+), браузър Edge (v 111+) и браузър Opera (v 97+) всички в производствените версии и в системата Android: на android браузър и Chrome за android.
Преди да преминете към този урок
Говорили сме за API за преглед на преходи преди в тази статия:
Бяхме обяснили какво представлява този API, как да го активирате във всички поддържани браузъри и как да го използвате, всичко това в ръководство стъпка по стъпка, с работещо приложение (MPA: многостранично приложение), с пълен изходен код, всички използващи само Vanilla JavaScript.
Трябва внимателно да прочетете внедряването на CSS, преди да продължите с този урок, защото няма да обясняваме отново API за преходи на изглед.
След това във втора статия, в същата тема, говорихме за използването на същия View Transitions API, но използвахме ReactJS.
Сега ще продължим със същия подход, но сега използвайки новия NextJS 13 с рутер за приложения и без да използваме допълнителни библиотеки на трети страни, всичко това използвайки CSS.
Това, което изграждаме
В тази статия ще създадем многостранично приложение, използвайки NextJS 13 и структурата на App Router, ще използваме новия API за преходи на изгледи, за да създаваме анимации, когато навигираме между различни изгледи (страници) и всичко това, използвайки само CSS.
В нашето приложение имаме три различни анимации:
- Вижте анимация (пораснете)
- Заглавна анимация (слайд отдясно)
- Анимация на съдържанието (слайд отляво)
Това е анимиран GIF, показващ окончателното ни приложение в действие:
Да кодираме
Първо ще създадем ново приложение NextJS 13 с активиран рутер за приложения:
npx create-next-app@latest
Не забравяйте да изберете „Да“ за рутера на приложението:
Сега трябва да изчистим кода:
За src/app/global.css:
@tailwind base; @tailwind components; @tailwind utilities;
И за src/app/page.tsx
export default function Home() { return (<></>)}
Ще започнем паралелно с разширяването на типа документ по подразбиране в NextJS, за да добавим новия експериментален API на View Transinions:
В папката src създайте нова папка: types и в нея създайте файл с име: extendedDocument.ts
export interface ExtendedDocument extends Document { startViewTransition?: any; }
Ще използваме този нов тип extendedDocument, за да заменим документа по подразбиране в нашия код NextJS.
Със същата логика ще разширим куката useRouter от NextJS, за да я накараме да поддържа новия API за преходи на преглед:
useAnimatedRouter кука:
В папката src създайте нова папка: hook и в нея създайте файл с име: useAnimatedRouter.ts
"use client"; import { ExtendedDocument } from "@/types/extendedDocument"; import { useRouter } from "next/navigation"; export default function useAnimatedRouter() { const router = useRouter(); const viewTransitionsStatus = () => { const extendedDocument = document as ExtendedDocument; let status = "Opss, Your browser doesn't support View Transitions API"; if (extendedDocument?.startViewTransition) { status = "Yess, Your browser support View Transitions API"; } return status; }; // Navigate to the new route const animatedRoute = (url: string) => { const extendedDocument = document as ExtendedDocument; if (!extendedDocument.startViewTransition) { return router.push(url); } else { extendedDocument.startViewTransition(() => { router.push(url); }); } }; return { animatedRoute, viewTransitionsStatus }; }
Тази кука експортира две функции:
- viewTansitionsStatus: Проверете дали браузърът поддържа новия API на View Transitions.
- animatedRoute: Капсулирайте метода по подразбиране router.push() и променя поведението му, ако браузърът поддържа нашия API, той го капсулира с функцията startViewTransition() (моля, вижте предишните статии за повече подробности относно това функция), ако не, тя ще се върне с поведението по подразбиране на router.push()
animatedLink компонент
Сега ще презапишем поведението по подразбиране на компонента NextJS Link, за да го накараме да поддържа новия API за преходи на изгледи:
В папката src създайте нова папка: components,и в нея създайте файл: animatedLink.tsx
import useAnimatedRouter from "@/hooks/useAnimatedRouter"; import Link from "next/link"; import React from "react"; type Props = { href: string; children: React.ReactNode; }; export default function AnimatedLink({ href, children }: Props) { const { animatedRoute } = useAnimatedRouter(); return ( <Link href={href} onClick={() => { animatedRoute(href); }} passHref > {children} </Link> ); }
Както можете да видите, ние използваме функцията animatedRoute() от нашата новосъздадена кука, за да презапишем поведението по подразбиране onClick на компонента Link.
И ние предаваме подпорите passHref тук, това ще позволи на компонента Link да предаде подпорката href на децата.
Компонент на заглавката:
import Link from "next/link"; import React from "react"; import AnimatedLink from "./animatedLink"; export default function Header() { return ( <div className="bg-slate-700 text-slate-50 py-4 "> <div className="container mx-auto flex gap-2"> <AnimatedLink href="/">Home</AnimatedLink> <AnimatedLink href="/about">About</AnimatedLink> <AnimatedLink href="/contact">Contact</AnimatedLink> </div> </div> ); }
Тук използваме компонента AnimatedLink като компонента Link по подразбиране. За да посочите трите страници: Начало, Информация и Контакти.
Компонент на долния колонтитул:
"use client"; import useAnimatedRouter from "@/hooks/useAnimatedRouter"; import React from "react"; export default function Footer() { const { viewTransitionsStatus } = useAnimatedRouter(); return ( <footer className="bg-gray-800 opacity-75 text-white p-1 text-center fixed bottom-0 left-0 right-0"> <span>{viewTransitionsStatus()}</span> </footer> ); }
Използваме функцията viewTransitionsStatus() от нашата нова създадена кука: useAnimatedRouter, за да покажем съобщение в долната част на нашето приложение.
Файл с оформление
Сега във файла Layout.tsx в папката src/app променете кода, за да включите компонентите ‹Header/› и ‹Footer/›
"use client"; import Header from "@/components/header"; import "./globals.css"; import type { Metadata } from "next"; import { Inter } from "next/font/google"; import Footer from "@/components/footer"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body className={inter.className}> <Header /> {children} <Footer /> </body> </html> ); }
Нашите три страници:
Променете page.tsx в папката src/app по следния начин:
export default function Home() { return ( <div className="flex flex-col h-screen items-center justify-center bg-amber-100 gap-10"> <h1 className="text-4xl pageHeader">Home Page</h1> <p className="mx-10 pageContent text-center line-clamp-3"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac urna auctor, viverra sapien. Donec euismod turpis eget massa lobortis, eget scelerisque justo. </p> </div> ); }
Това е нашата начална страница.
Същото за страницата Информация в папката: src/app/about, създайте нов файл с име: page.tsx
export default function About() { return ( <div className="flex flex-col h-screen items-center justify-center bg-amber-200 gap-10"> <h1 className="text-4xl pageHeader">About Page</h1> <p className="mx-10 pageContent text-center line-clamp-3"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac urna auctor, viverra sapien. Donec euismod turpis eget massa lobortis, eget scelerisque justo. </p> </div> ); }
В папката: src/app/contact създайте нов файл с име: page.tsx
export default function Contact() { return ( <div className="flex flex-col h-screen items-center justify-center bg-amber-300 gap-10"> <h1 className="text-4xl pageHeader">Contact Page</h1> <p className="mx-10 pageContent text-center line-clamp-3"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ac urna auctor, viverra sapien. Donec euismod turpis eget massa lobortis, eget scelerisque justo. </p> </div> ); }
Разгледайте внимателно таговете ‹h1› и ‹p› в трите страници:
- ‹h1› съдържат класа: pageHeader
- ‹p› съдържат класа: pageContent
Ще използваме тези CSS класове, за да анимираме тези секции по-късно
globals.css файл
Сега ще използваме магията на View Transitions API, за да анимираме нашето приложение, използвайки само CSS.
Цялата магия се случва в този файл: globals.css:
@tailwind base; @tailwind components; @tailwind utilities; /* Animate the page header separatly */ .pageHeader { view-transition-name: page-header; } /* Animate the page content separatly */ .pageContent { view-transition-name: page-content; } ::view-transition-old(root) { animation: fade-and-scale-out 0.5s ease-in-out 1 forwards; } ::view-transition-new(root) { animation: fade-and-scale-in 1s ease-in-out 1 forwards; } ::view-transition-old(page-header) { animation: hide 1s ease-in-out 1 forwards; } ::view-transition-new(page-header) { animation: slide-right 2s ease-in-out 1 forwards; } ::view-transition-old(page-content) { animation: hide 1s ease-in-out 1 forwards; } ::view-transition-new(page-content) { animation: slide-left 2.5s ease-in-out 1 forwards; } /* First Animation */ @keyframes fade-and-scale-in { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } @keyframes fade-and-scale-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0); } } /* Second Animation */ @keyframes hide { from { opacity: 1; } to { opacity: 0; } } @keyframes slide-left { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: translateX(0); } } @keyframes slide-right { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: translateX(0); } }
Ще обясним всяка част от този файл:
@tailwind base; @tailwind components; @tailwind utilities;
Това е част от конфигурацията по подразбиране на TailwindCSS, присъства по подразбиране в нашия файл globals.css.
... ::view-transition-old(root) { animation: fade-and-scale-out 0.5s ease-in-out 1 forwards; } ::view-transition-new(root) { animation: fade-and-scale-in 1s ease-in-out 1 forwards; } ... @keyframes fade-and-scale-in { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } } @keyframes fade-and-scale-out{ from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0); } }
Тази част от кода ще анимира основния елемент на изгледите (нашите страници), състоянието на анимацията се променя между старото и новото състояние, за това имаме две анимации на CSS ключови кадри:
- избледняване и мащабиране
- избледняване и мащабиране
... /* Animate the page header separatly */ .pageHeader { view-transition-name: page-header; } ... ::view-transition-old(page-header) { animation: hide 1s ease-in-out 1 forwards; } ::view-transition-new(page-header) { animation: slide-right 2s ease-in-out 1 forwards; } ... /* Second Animation */ @keyframes hide { from { opacity: 1; } to { opacity: 0; } } @keyframes slide-right { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: translateX(0); } }
В тази част от кода създадохме нов контейнер за преход на изглед, с помощта на: име на изглед-преход: заглавка на страницата, с присвоен на CSS клас: pageHeader
Ще използваме това име: „page-header“, за да зададем нова анимация (скриване и плъзгане надясно).
... /* Animate the page header separatly */ .pageContent { view-transition-name: page-content; } ... ::view-transition-old(page-content) { animation: hide 1s ease-in-out 1 forwards; } ::view-transition-new(page-header) { animation: slide-left 2.5s ease-in-out 1 forwards; } ... /* Second Animation */ @keyframes hide { from { opacity: 1; } to { opacity: 0; } } @keyframes slide-left { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: translateX(0); } }
Със същата логика създадохме нов контейнер за преход на изглед с помощта на: име на преход на изглед: съдържание на страница, с присвоено на CSS класа: pageContent.
Ще използваме това име: „страница-съдържание“, за да зададем нова анимация (скриване и плъзгане наляво).
Пълен изходен код
https://github.com/adelpro/nextjs-view-transitions
На обикновен английски
Благодарим ви, че сте част от нашата общност! Преди да тръгнете:
- Не пропускайте да ръкопляскате и следвайте писателя! 👏
- Можете да намерите още повече съдържание в PlainEnglish.io 🚀
- Регистрирайте се за нашия безплатен седмичен бюлетин. 🗞️
- Следвайте ни в Twitter (X), LinkedIn, YouTube и Раздори.