mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Add page transitions example (#2613)
This commit is contained in:
parent
6781a75d8b
commit
337471d684
29
examples/page-transitions/README.md
Normal file
29
examples/page-transitions/README.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/page-transitions)
|
||||
|
||||
# Example app with custom page transitions
|
||||
|
||||
## How to use
|
||||
|
||||
Download the example [or clone the repo](https://github.com/zeit/next.js):
|
||||
|
||||
```bash
|
||||
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/page-transitions
|
||||
cd page-transitions
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
|
||||
```bash
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
|
||||
|
||||
```bash
|
||||
now
|
||||
```
|
||||
|
||||
## The idea behind the example
|
||||
|
||||
Being able to animate out old content and animate in new content is a fairly standard thing to do these days. We can hijack the route change and do any animations that we want: sliding, cross fading, scaling, et al.
|
19
examples/page-transitions/package.json
Normal file
19
examples/page-transitions/package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "page-transitions",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "NODE_ENV=development node server.js",
|
||||
"build": "next build",
|
||||
"start": "NODE_ENV=production node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"compression": "^1.7.0",
|
||||
"express": "^4.15.3",
|
||||
"next": "latest",
|
||||
"next-routes": "^1.0.40",
|
||||
"raf": "^3.3.2",
|
||||
"react": "^15.4.2",
|
||||
"react-dom": "^15.4.2"
|
||||
},
|
||||
"license": "ISC"
|
||||
}
|
21
examples/page-transitions/pages/_document.js
Normal file
21
examples/page-transitions/pages/_document.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from 'react'
|
||||
import Document, { Head, Main, NextScript } from 'next/document'
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
export default class CustomDocument extends Document {
|
||||
render () {
|
||||
return (<html lang='en-US'>
|
||||
<Head>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||
<meta name='robots' content='noindex' />
|
||||
<link rel='stylesheet' href='/static/style.css' />
|
||||
</Head>
|
||||
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</html>)
|
||||
}
|
||||
}
|
39
examples/page-transitions/pages/index.js
Normal file
39
examples/page-transitions/pages/index.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { PureComponent } from 'react'
|
||||
import raf from 'raf'
|
||||
import { Router } from '../routes'
|
||||
import Main from './main'
|
||||
|
||||
// -----------------------------------------------
|
||||
|
||||
Router.onRouteChangeStart = () => {
|
||||
const $container = document.getElementById('container')
|
||||
const $clone = $container.cloneNode(true)
|
||||
|
||||
document.body.classList.add('loading')
|
||||
$clone.classList.add('clone')
|
||||
|
||||
raf(() => {
|
||||
$container.parentNode.insertBefore($clone, $container.nextSibling)
|
||||
$clone.classList.add('animate-out')
|
||||
$container.classList.add('animate-in')
|
||||
})
|
||||
|
||||
$clone.addEventListener('animationend', () => {
|
||||
document.body.classList.remove('loading')
|
||||
$container.classList.remove('animate-in')
|
||||
$clone.parentNode.removeChild($clone)
|
||||
}, { once: true })
|
||||
}
|
||||
|
||||
// -----------------------------------------------
|
||||
|
||||
export default class Index extends PureComponent {
|
||||
static async getInitialProps ({ query }) {
|
||||
const pathname = query.slug || '/'
|
||||
return { pathname }
|
||||
}
|
||||
|
||||
render () {
|
||||
return <Main {...this.props} />
|
||||
}
|
||||
}
|
38
examples/page-transitions/pages/main.js
Normal file
38
examples/page-transitions/pages/main.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Head from 'next/head'
|
||||
import { Link } from '../routes'
|
||||
|
||||
// -----------------------------------------------
|
||||
|
||||
export default class Main extends PureComponent {
|
||||
render () {
|
||||
return (<div>
|
||||
<Head>
|
||||
<title>{this.props.pathname} - Page Transitions</title>
|
||||
</Head>
|
||||
|
||||
<header>
|
||||
<Link to='/'>
|
||||
<a className={this.props.pathname === '/' ? 'active' : ''}>Homepage</a>
|
||||
</Link>
|
||||
|
||||
<Link route='main' params={{ slug: 'about' }}>
|
||||
<a className={this.props.pathname === 'about' ? 'active' : ''}>About</a>
|
||||
</Link>
|
||||
|
||||
<Link route='main' params={{ slug: 'contact' }}>
|
||||
<a className={this.props.pathname === 'contact' ? 'active' : ''}>Contact</a>
|
||||
</Link>
|
||||
</header>
|
||||
|
||||
<div id='container' className={`page-${this.props.pathname}`}>
|
||||
<h1 dangerouslySetInnerHTML={{ __html: this.props.pathname }} />
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
|
||||
Main.propTypes = {
|
||||
pathname: PropTypes.string.isRequired
|
||||
}
|
6
examples/page-transitions/routes.js
Normal file
6
examples/page-transitions/routes.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
const nextRoutes = require('next-routes')
|
||||
const routes = nextRoutes()
|
||||
|
||||
routes.add('main', '/:slug/:child?', '')
|
||||
|
||||
module.exports = routes
|
12
examples/page-transitions/server.js
Normal file
12
examples/page-transitions/server.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
const next = require('next')
|
||||
const routes = require('./routes')
|
||||
const express = require('express')
|
||||
const compression = require('compression')
|
||||
|
||||
const port = process.env.PORT || 3000
|
||||
const dev = process.env.NODE_ENV !== 'production'
|
||||
|
||||
const app = next({ dev })
|
||||
const handle = routes.getRequestHandler(app)
|
||||
|
||||
app.prepare().then(express().use(compression()).use(handle).listen(port))
|
99
examples/page-transitions/static/style.css
Normal file
99
examples/page-transitions/static/style.css
Normal file
|
@ -0,0 +1,99 @@
|
|||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
/* ------------------------------------------- */
|
||||
|
||||
header {
|
||||
z-index: 100;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 20px;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
header a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
header a:not(:last-child) {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
header a.active {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* ------------------------------------------- */
|
||||
|
||||
@keyframes animateIn {
|
||||
from {
|
||||
transform: translate3d(100vw, 0, 0);;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animateOut {
|
||||
to {
|
||||
transform: translate3d(-100vw, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------- */
|
||||
|
||||
#container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
box-shadow: inset 0 0 0 20px;
|
||||
background: #FFF;
|
||||
}
|
||||
|
||||
#container.page-about {
|
||||
background: tan;
|
||||
}
|
||||
|
||||
#container.page-contact {
|
||||
background: violet;
|
||||
}
|
||||
|
||||
#container h1 {
|
||||
font-size: 10vw;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
#container[class*="animate-"] {
|
||||
position: fixed;
|
||||
animation: animateIn .75s ease-in-out forwards;
|
||||
transform-origin: center;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
#container.animate-out {
|
||||
animation-name: animateOut;
|
||||
}
|
||||
|
||||
.loading #container:not(.clone) h1 {
|
||||
opacity: 0;
|
||||
animation: fadeIn 1s .15s ease-in-out forwards;
|
||||
}
|
Loading…
Reference in a new issue