So I am using Next 13 loading.tsx
to showcase loading before the final page renders.
I am using framer motion
to showcase one animation with icon moves from the bottom-left
corner of the screen to the top-right
corner of the screen, and I was hoping to showcase the rendered page after that, but what happens currently is that if the page bundles loaded early in the browser instead of showing the full animation it would just show page directly after half of the animation.
So let's say the animation length is 1s
but the new page renders in 0.5 seconds
then the animation won't fully complete.
I want to quickly show this animation as full before the page renders. How can I achieve that? Do I have to put wait somewhere in the component I didn't like that idea.
// loading.tsx
"use client";
import React from 'react';
import { motion } from 'framer-motion';
import KikiAndJiji from '../icons/KikiAndJiji';
export default function Loading() {
const flyAnimation = {
initial: { x: 0, y: '100vh' },
animate: { x: '100vw', y: '-100vh' },
};
const flyTransition = {
duration: 3,
ease: 'linear',
repeat: Infinity,
};
return (
<motion.div
className="h-screen w-screen"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<motion.div
className="flying-image h-full w-full"
variants={flyAnimation}
initial="initial"
animate="animate"
transition={flyTransition}
>
<KikiAndJiji width="200" height="200" color="white" />
</motion.div>
</motion.div>
);
}
// page.tsx
"use client";
import { BsChevronCompactLeft, BsChevronCompactRight } from "react-icons/bs";
import QuestionsSlide from "./components/QuestionSlide";
import { store } from "./store";
import "./style.css";
import { useSnapshot } from "valtio";
import { QuestionType } from "../models/types";
export default function Page() {
const snapshot = useSnapshot(store);
const goLeft = () => {
if (store.questionNumber > 0) {
store.questionNumber--;
}
};
const currentQuestionIsNotDecided = (question: { question: string; type: QuestionType; }) => {
return question.question === "" || question.type === QuestionType.NOT_DECIDED;
}
const goRight = () => {
if (currentQuestionIsNotDecided(store.questions[store.questionNumber])) {
return;
}
if (store.questionNumber === store.questions.length - 1) {
store.questions.push({ question: "", type: QuestionType.NOT_DECIDED });
}
store.questionNumber++;
};
const submitSurvey = async () => {
if (currentQuestionIsNotDecided(store.questions[store.questionNumber])) {
return;
}
store.questions = store.questions.filter(question => !currentQuestionIsNotDecided(question));
const res = await fetch("create-survey/api", {
method: "POST", body: JSON.stringify({
surveyName: store.surveyName,
questions: [...store.questions]
})
});
const data = await res.json();
console.log(data);
};
const editSurveyName = (event: React.ChangeEvent<HTMLInputElement>) => {
store.surveyName = event.target.value;
};
return (<main className="flex flex-col h-screen">
<nav className="flex justify-center p-3">
<input type="text" className="text-2xl bg-transparent outline-none" value={store.surveyName} onChange={editSurveyName} />
</nav>
<section className="flex justify-between items-center h-full">
<button className={`text-6xl w-1/12 flex justify-center ${store.questionNumber === 0 && "btn-hide"}`} onClick={goLeft}><BsChevronCompactLeft /></button>
<QuestionsSlide />
<button className="text-6xl w-1/12 flex justify-center" onClick={goRight}><BsChevronCompactRight /></button>
</section>
<footer className="flex justify-end p-4">
<button className="btn-primary" onClick={submitSurvey}>Finish</button>
</footer>
</main>);
}
My application is open source if you want to check it out, currently above code is not yet pushed. Check out here Github