make page transition easier for next.js | 让next.js的页面切换动画更简单
quick glance https://www.youtube.com/watch?v=zpzbNA0J9CM&list=PLM1v95K5B1ntVsYvNJIxgRPppngrO_X4s
components/wrapper.js
import w from 'next-page-transition'
import { zoomfade } from 'next-page-transition/dist/presets'
export const wrapper = w(zoomfade())
pages/index.js
import Link from 'next/link'
import wrapper from '../components/wrapper'
const Index = () => (<div>
<p>home page</p>
<Link href="/about"><a>about</a></Link>
</div>)
export default wrapper(Index)
note Do not use Router.onRouteChangeStart=xxx
in your code, use routerEvents.on('routeChangeStart', xxx)
refer next-router-events | 不要在你的代码中使用 Router.onRouteChangeStart=xxx
这样的代码,如果需要绑定next.js的路由事件请使用routerEvents.on('routeChangeStart', xxx)
,详情参考 next-router-events
note To clean the hook created by this package (most cases you do not need to), you can use wrapper.destory()
to unregister | 要清理前面提到的router事件绑定(大部分时候应该是不需要清理的),你可以使用 wrapper.destory()
来清理
- basic | 基本使用 https://codesandbox.io/s/next-page-transition-basic-1qyps
_app.js
https://codesandbox.io/s/next-page-transition-with-app-oqr8o?file=/pages/_app.js- side nav | 侧边导航 https://codesandbox.io/s/next-page-transition-with-menu-hk63z?file=/pages/_app.js
import w from 'next-page-transition'
const wrapper = w({
duration: 600, //transition duration | 动画时长
containerProps: { //props for container | 容器元素的属性
style: {
position: 'relative'
}
},
frameProps: { //props for frame | 页面外框元素的属性
style: {
position: 'absolute',
width: '100%',
opacity: 0,
transition: `${duration}ms ease-in-out`,
}
},
transitionStyles: { //transition styles | 各个状态的style
inital: { opacity: 0 }, // before come into view
entering: { opacity: 1, }, // entering view
entered: { opacity: 1 }, // stay in view
exiting: { opacity: 0, }, // leaving view, while next page entering
exited: { opacity: 0 }, // left view, right before removed
},
})
import React from 'react'
import App from 'next/app'
import w from 'next-page-transition'
import { zoomfade } from 'next-page-transition/dist/presets'
const wrapper = w(zoomfade())
const transMap = new Map()
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
if (!transMap[Component]) transMap[Component] = wrapper(Component)
const Trans = transMap[Component]
return (<Trans {...pageProps} />)
}
}
export default MyApp
use getTransitionConfig
function | 给组件添加 getTransitionConfig
方法
import wrapper from '../components/wrapper'
import { fade } from 'next-page-transition/dist/presets'
const transitionConfig = fade(1000)
transitionConfig.frameProps.style.transform = 'none'
const About = () => (<div>
<p>about page</p>
</div>)
About.getTransitionConfig = () => transitionConfig
export default wrapper(About)
getTransitionConfig
will get called with two params(from page component and to page component) when navigation happen
当导航发生时getTransitionConfig
会被调用并且传入两个参数(上一个页面组件和新的页面组件)
About.getTransitionConfig = (Last,Current) => {
if(Last && Last === About){
console.log('leaving about and entering',Current)
}else if(Current === About){
console.log('entering about and leaving',Last)
}
}
you may need something do not animate with page, or something like template, for example side-nav-bar
你可能会需要一些不跟着页面做动画的东西,或者像是类似模板概念的东西,比如说 侧边导航条
import w from 'next-page-transition'
import { zoomfade } from 'next-page-transition/dist/presets'
import SideBar from './SideBar'
const wrapper = w({
...zoomfade(),
Container: (props) => {
const { children } = props
return (<div style={{
position: 'absolute',
width: '100vw',
height: '100vh',
overflow: 'hidden',
}}>
{children}
<SideBar />
</div>)
},
})
Container
by default is a div, where props
come from containerProps
in config
(props) => (<div {...props} />)
you can refer wrapper.js and run example for real code and result
you can refer wrapper.js and run example for real code and result
import { zoomfade } from 'next-page-transition/dist/presets'
- fade
- zoom
- zoomfade
- zoomrotate
- flipVertical
- flipHorizontal
- slideUp
- slideDown
- slideLeft
- slideRight