Reputation: 53
I use Next.js, React, TypeScript and Framer Motion.
I don't use react router.
I would like to do a transition between pages.
I've found how to do the transition from right to the left when I change my page (in _app.tsx
).
But it's the same transition if I follow the link with the arrow right and with the arrow left.
I would like to do a transition from right to left with the arrow right and a transition from left to right with the arrow left.
my _app.tsx
:
import '../public/css/style.scss';
import { animate, AnimateSharedLayout, motion } from 'framer-motion';
import { useRouter } from "next/router";
import App from "next/app";
//import Strategie from './strategie'
export default class MyApp extends App {
render(){
const { Component, pageProps } = this.props;
const { router } = this.props;
// const { router } = this.props;
return <>
<motion.div key={router.route} initial="pageInitial" animate="pageAnimate" exit="pageExit" variants={{
pageInitial: {
opacity: 0,
x: "100%",
},
pageAnimate: {
opacity: 1,
x: 0,
transition: {
ease: "easeIn",
duration: 0.5,
}
},
pageExit: {
// filter: `invert()`,
opacity: 0,
}
}}>
<Component {...pageProps} />
</motion.div>
</>
}
}
My page where there are 2 arrows (I have several pages like this) :
import React from "react";
import HomePageBlock, {IdHomePageBlockProps} from '../components/common/home pages/homePage-block';
import ButtonStartProject from "../components/buttons/button-startProject";
import Link from "next/link";
import Sidebar from "../components/common/sidebar/sidebar";
interface IdHomePageSingularityProps {
title?: string;
}
interface IdHomePageSingularityState{
homePageInfos: IdHomePageBlockProps[]
}
export default class HomePageSingularity extends React.Component<IdHomePageSingularityProps, IdHomePageSingularityState>{
constructor(props){
super(props);
this.state = {
homePageInfos: [
{
title: <>Révélons <br/> ta singularité</>,
subTitle: "notre expertise",
description: <>Nombreux sont les projets qui émergent aujourd'hui, alors comment se démarquer quand tu as un projet bienveillant sans perdre en efficacité ? <br/> Chez Ben&Jo nous concevons des identités visuelles basés sur une stratégie cohérente. Nous inventerons pour ton projet un univers visuel unique et impactant !</>,
img: { url : "/img/home-pages/singularity.svg"},
buttonDiscover: <>
<Link href="/brandingIndex">
<a className="buttonDiscover" >DECOUVRE NOTRE SAVOIR FAIRE !</a>
</Link></>,
buttonStartProject: <><ButtonStartProject /></>,
imgFingersBox: { url : "/img/home-pages/fingersBox.svg"},
arrowRight: <>
<Link href="/homePageSucces">
<img src="/img/home-pages/arrowRight.svg" />
</Link></>,
arrowLeft: <>
<Link href="/homePageStrategie">
<img src="/img/home-pages/arrowLeft.svg" />
</Link>
</>,
}
]
}
}
render(){
const { homePageInfos } = this.state;
return <>
<div className="home__singularity">
<div><Sidebar /></div>
{ homePageInfos && homePageInfos.map((item, index) => {
return <HomePageBlock key={"home__singularity-block_" + index }
{...item} className="home__singularity-block"/>
})
}
</div>
</>
}
}
The page where I build the components:
import React from 'react';
import FingersBox from './fingersBox';
export interface IdHomePageBlockProps {
title?: {};
subTitle?: string;
description?: {};
img?: {url: string, alt?: string};
buttonDiscover?: {};
buttonStartProject?: {};
arrowRight?: {};
arrowLeft?: {};
className?: string;
imgFingersBox?: {url: string, alt?: string};
}
export interface IdHomePageBlockState{
}
export default class HomePageBlock extends React.Component<IdHomePageBlockProps, IdHomePageBlockState>{
render(){
const { title, subTitle, description, img, buttonDiscover, buttonStartProject, arrowRight, arrowLeft, className } = this.props;
return <>
<div className={className + ' homePage-block'}>
<header>
<div className="homePage-block__imageFingers-box"><FingersBox /></div>
<div className="homePage-block__subTitle">{subTitle}</div>
<div className="homePage-block__buttonStartProject">{buttonStartProject}</div>
</header>
<body>
<main>
<div className="homePage-block__title">{title}</div>
<div className="homePage-block__description">{description}</div>
<div className="homePage-block__buttonDiscover">{buttonDiscover}</div>
</main>
<aside>
<div className="homePage-block__image-box">
<img src={img.url} alt={img.alt} />
</div>
</aside>
</body>
<footer>
<div className="homePage-block__arrowLeft">{arrowLeft}</div>
<div className="homePage-block__arrowRight">{arrowRight}</div>
</footer>
</div>
</>
}
}
As you can see, there is no button, just links.
Upvotes: 1
Views: 2078
Reputation: 2057
You can use dynamic variants in framer motion to achieve this.
export default class MyApp extends App {
constructor(props) {
super(props)
this.state = { direction: 'left' }
}
changeDirection(direction: string) {
this.setState({
direction
});
}
render(){
const { direction } = this.state
const { Component, pageProps } = this.props;
const { router } = this.props;
// const { router } = this.props;
return <>
<motion.div key={router.route} custom={direction} initial="pageInitial" animate="pageAnimate" exit="pageExit" variants={{
pageInitial: direction => ({
opacity: 0,
x: direction === 'left' ? "100%" : "-100%",
}),
pageAnimate: {
opacity: 1,
x: 0,
transition: {
ease: "easeIn",
duration: 0.5,
}
},
pageExit: {
// filter: `invert()`,
opacity: 0,
}
}}>
<Component changeDirection={this.changeDirection} {...pageProps} />
</motion.div>
</>
}
}
In the actual Page Component, you might need to figure out a way to change the direction as required before the navigation is initiated.
import React from "react";
import { withRouter } from 'next/router'
import HomePageBlock, {IdHomePageBlockProps} from '../components/common/home pages/homePage-block';
import ButtonStartProject from "../components/buttons/button-startProject";
import Link from "next/link";
import Sidebar from "../components/common/sidebar/sidebar";
interface IdHomePageSingularityProps {
title?: string;
}
interface IdHomePageSingularityState{
homePageInfos: IdHomePageBlockProps[]
}
class HomePageSingularity extends React.Component<IdHomePageSingularityProps, IdHomePageSingularityState>{
constructor(props){
super(props);
this.state = {
homePageInfos: [
{
title: <>Révélons <br/> ta singularité</>,
subTitle: "notre expertise",
description: <>Nombreux sont les projets qui émergent aujourd'hui, alors comment se démarquer quand tu as un projet bienveillant sans perdre en efficacité ? <br/> Chez Ben&Jo nous concevons des identités visuelles basés sur une stratégie cohérente. Nous inventerons pour ton projet un univers visuel unique et impactant !</>,
img: { url : "/img/home-pages/singularity.svg"},
buttonDiscover: <>
<Link href="/brandingIndex">
<a className="buttonDiscover" >DECOUVRE NOTRE SAVOIR FAIRE !</a>
</Link></>,
buttonStartProject: <><ButtonStartProject /></>,
imgFingersBox: { url : "/img/home-pages/fingersBox.svg"},
arrowRight: <>
<a onClick={this.handleRightClick} href="/homePageSucces">
<img src="/img/home-pages/arrowRight.svg" />
</a></>,
arrowLeft: <>
<a onClick={this.handleLeftClick} href="/homePageStrategie">
<img src="/img/home-pages/arrowLeft.svg" />
</a>
</>,
}
]
}
}
const handleRightClick = (e) => {
e.preventDefault()
this.changeDirection('right')
this.props.router.push('/homePageSucces')
}
const handleLeftClick = (e) => {
e.preventDefault()
this.changeDirection('left')
this.props.router.push('/homePageStrategie')
}
render(){
const { homePageInfos } = this.state;
return <>
<div className="home__singularity">
<div><Sidebar /></div>
{ homePageInfos && homePageInfos.map((item, index) => {
return <HomePageBlock key={"home__singularity-block_" + index }
{...item} className="home__singularity-block"/>
})
}
</div>
</>
}
}
export default withRouter(HomePageSingularity)
Upvotes: 2