Gatsby页面动画转换教程:使你的页面更有趣

2019 年 6 月 2 日 前端之巅

作者 | Chris Nwamba
译者 | 王强

GatsbyJS 是一个基于 React 的静态站点生成器,由 GraphQL 提供支持。开发者可以先写好网站的代码和框架,然后用 Gatsby 把它们转换为单个 HTML 文件,加上所有的静态资源放到一个目录里。Gatsby 速度很快,而且已经预配置好了服务工作者、代码分割、服务器端渲染、智能图像加载、资产优化和数据预取等工作。但这些都是老生常谈了,下面就进入本文的正题。

有时,上面提到的那些东西仍不足以让你的用户在访问网站时获得出色的体验。如今用户的口味如此挑剔,开发者几乎没法满足他们,而且要让他们满意而付出的成本高不可攀。在本教程中,我们将介绍一些在 Gatsby 应用中添加页面转换的方法,这样能让你的网站变得更有趣、更吸引人一些。

截至目前 Gatsby 并没有开箱即用的转换效果,所以我们得自己做些研究。

准备工作

开始学习本教程前你需要具备 React.js 的入门知识,这样才能看懂后文用到的代码。想要解释清楚某件事物的工作原理,最好的方法就是从头构建一次来做演示。因此我们将创建一个新的 Gatsby 应用,用它来展示为页面添加动画的几种方法。

创建新的 Gatsby 应用

如果你还没装过 Gatsby,请使用以下命令安装 Gatsby CLI 工具:

npm install -g gatsby-cli

安装完成后就可以运行 Gatsby 的指定命令来创建、构建和部署我们的应用。要创建新的 Gatsby 项目,请在目标目录中打开终端窗口并运行:

gatsby new transitions-demo

这将为你创建一个新的 Gatsby 项目。你可以转到项目文件夹并运行 server 命令以启动开发服务器。

cd transitions-demo && gatsby develop

这将在 localhost:8000 上启动项目,在浏览器中打开这个地址就能看到你的 Gatsby 项目了!

选项 1:使用 React 转换库添加页面转换

React 转换库(React transition group)是向 Gatsby 应用添加转换的首选方法,也是最常见的方法。值得注意的是它并不是专门设计的动画库,因此无法为动画设置样式。相反,它暴露了转换阶段、管理类和组元素,操纵 DOM 的方法也很有用,让转换动画更加容易实现。

安装依赖项

那我们就开始安装转换库,然后看看怎么用它做转换效果。

npm install react-transition-group

它将监视 DOM 中元素的 entry 和 exit 状态,然后根据我们的自定义转换样式应用相应的转换效果。

下一个要安装的包是 Gatsby 布局插件。我们能用它提供转换效果所需的 location 属性,并在每个页面上注入我们的布局。

npm install gatsby-plugin-layout
配置 Gatsby

安装依赖项后我们先要配置 gatsby-config.js 文件,以应用我们刚刚安装的布局。打开文件并在插件数组中添加布局插件:

module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `My new Gatsby site`,
author: `@gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-plugin-layout`,
options: {
component: require.resolve(`./src/layouts/index.js`),
},
},
],
}

为了使此插件正常工作,我们需要将 layout 文件从 components 文件夹内移动到项目文件 src 文件夹的根目录,并将 layout.js 文件重命名为 index.js。然后在 components 文件夹中创建一个名为 transition.js 的新文件来托管我们的转换逻辑实现。之后应用结构应该如下所示。

很好,整理好这些后我们就该在页面中实现这些转换效果了。打开我们在 components 文件夹中创建的 transition.js 文件,并加入下面的代码。

import React from "react"
import {
TransitionGroup,
Transition as ReactTransition,
} from "react-transition-group"
const timeout = 500
const getTransitionStyles = {
entering: {
position: `absolute`,
opacity: 0,
},
entered: {
transition: `opacity ${timeout}ms ease-in-out`,
opacity: 1,
},
exiting: {
transition: `opacity ${timeout}ms ease-in-out`,
opacity: 0,
},
}
class Transition extends React.PureComponent {
render() {
const { children, location } = this.props
return (
<TransitionGroup>
<ReactTransition
key={location.pathname}
timeout={{
enter: timeout,
exit: timeout,
}}
>
{status => (
<div
style={{
...getTransitionStyles[status],
}}
>
{children}
</div>
)}
</ReactTransition>
</TransitionGroup>
)
}
}
export default Transition

一起来看看代码。首先,我们从之前安装的 react-transition-group 包导入了 TransitionGroup 和 ReactTransition。TransitionGroup 帮助我们管理 DOM 中组件的挂载和卸载,而 ReactTransition 跟踪传递给它的元素的 entry 和 exit 状态。

接下来我们声明了一个 timeout 变量,它负责指定动画的持续时间。然后我们定义了包含动画 CSS 样式的 getTransitionStyles 对象。最后为了方便,我们解构了 prop 中的 children 和 location。

请注意,ReactTransition 接受一个键 key={location.pathname},来跟踪 DOM 中元素的 entry 和 exit。有了它,我们就能根据 DOM 中页面 / 元素的 status(entering,exiting,entered)来应用样式。

以上就是我们的转换组件。接下来我们要做的是使用这个组件来包装我们所有的页面。我们可以将应用中的所有页面作为 children 包装在 layout 组件中,然后用转换组件包装整个 layout 组件。

这样,我们将在转换组件中定义的 location prop 就会生效,并在进入和退出 DOM 时为页面启用动画。打开 layouts 文件夹中的 index.js 文件,并加入下面的代码。

//src/layouts/index.js

import React from "react"
import PropTypes from "prop-types"
import { StaticQuery, graphql } from "gatsby"
import Header from "../components/header"
import "./layout.css"
import Transition from '../components/transition'

const Layout = ({ children, location }) => (
<StaticQuery
query={graphql`query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}`}
render={data => (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `0px 1.0875rem 1.45rem`,
paddingTop: 0,
}}
>
<Transition location = {location}>
{children}
</Transition>
</div>
</>
)}
/>
)
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout

在这里,我们导入了刚才创建的 Transition 组件,然后如前所述,我们用它来包装代表应用中所有页面的 children。我们还将 location prop 传递给 Transition 组件,以跟踪页面进入和退出 DOM 时的位置。

最后修改 pages 文件夹中的 index.js 文件来在主页上添加更多页面,以便测试转换效果。打开它并加入下面的代码:

// src/pages/index.js

import React from "react"
import { Link } from "gatsby"
import SEO from "../components/seo"

const IndexPage = () => (
<div>
<SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>

<Link to="/blog/">Go to my blog</Link> <br />
<Link to="/about/">Go to my about page</Link> <br />
<Link to="/contact/">Go to my contact page</Link> <br />
<Link to="/404/">404</Link> <br/>
<Link to="/page-2/">Go to page 2</Link>
</div>
)
export default IndexPage

好的,现在当我们运行应用时应该能看到在主页上呈现的所有页面,点击其中任何一个都应该会转换到新页面上。

选项 2:使用 Gatsby 页面转换插件添加页面转换

刚才讲的是第一种添加转换的方法。下面看一下另一种完全不同的法子,就是使用页面转换插件。gatsby-plugin-page-transitions 这个插件能够以声明方式添加页面转换,还能为项目中的任何页面设置自定义的页面转换效果。

和之前一样,我们将安装必要的依赖项并一步步演示。

安装依赖项
npm install --save gatsby-plugin-page-transitions
 配置Gatsby

安装完插件后,我们修改项目根目录中的 Gatsby 配置文件来把插件添加进来。打开 gatsby-config.js 并使用以下代码更新插件数组:

plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-page-transitions`,
{
resolve: 'gatsby-plugin-page-transitions',
options: {
transitionTime: 500
}
}
]
转换类型

gatsby-plugin-page-transitions 插件为我们提供了多种类型的转换效果,包括:

  • 默认转换

  • 自定义转换

  • 无转换效果

  • 多种转换效果

默认转换

先讲默认转换,其实它和上一个示例中的效果是一样的。我们只要在所有需要转换效果的页面中包装进这个插件就行了。

作为示例,这里将插件导入应用的主页和其它一些页面,并运行应用。

import React from "react"
import { Link } from "gatsby"
import SEO from "../components/seo"
import Header from "../components/header"
import PageTransition from 'gatsby-plugin-page-transitions';

const IndexPage = () => (
<PageTransition>
<Header siteTitle="Gatsby Default Starter" />
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>

<Link to="/blog/">Go to my blog</Link> <br />
<Link to="/about/">Go to my about page</Link> <br />
<Link to="/contact/">Go to my contact page</Link> <br />
</PageTransition>
)
export default IndexPage

现在运行应用时,我们就能看到和上一个示例完全相同的转换效果,因为这里使用的转换时间参数也是 500ms。

从实际结果来看转换似乎有点太快了。你可以为转换设置自己看得顺眼的持续时间,时间越长速度越慢。

自定义转换

自定义转换类型使开发者可以灵活地指定页面的转换样式。默认转换样式只会在新页面上执行一种透视动画转换效果,但你可以使用插件进行更多操作。例如你可以选择从浏览器一侧或从顶部开始转换到新页面,或者缩放转换到新页面,甚至来个漩涡转换效果等等。

要自定义转换效果,可以使用 CSS 定义转换样式,并将其作为 prop 传递给 PageTransition 元素。下面我们将 Index 和 About 页面中的默认转换效果改为自定义的滑动转换。

import React from "react"
import { Link } from "gatsby"
import Header from "../components/header"
import PageTransition from 'gatsby-plugin-page-transitions';

const IndexPage = () => (
<PageTransition
defaultStyle={{
transition: 'left 500ms cubic-bezier(0.47, 0, 0.75, 0.72)',
left: '100%',
position: 'absolute',
width: '100%',
}}
transitionStyles={{
entering: { left: '0%' },
entered: { left: '0%' },
exiting: { left: '100%' },
}}
transitionTime={500}
>
<Header siteTitle="Gatsby Default Starter" />
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>

<Link to="/blog/">Go to my blog</Link> <br /><br></br>
<Link to="/about/">Go to my about page</Link> <br /><br></br>
<Link to="/contact/">Go to my contact page</Link> <br />
</PageTransition>
)
export default IndexPage

在 about 页面中也更新上述代码,然后再次运行应用。现在两个页面应该都变成了滑动转换。

混合转换

显然你也可以在项目中使用多种转换类型。如果你愿意,可以为应用中的每个页面指定不同的转换效果。这里唯一要小心的是效果太多会对用户体验带来不利影响。

最好还是简洁一些,但是如果你还是想要在不同的页面中实现不同的转换效果,只要分别设置 PageTransition 元素的样式就行了! 这样每个页面就都有了自己的转换效果。

结语

如果你的应用页面中塞满了的内容,用户要一直向下滚动到页面底部才能看完,那么当页面转换进出时可能会遇到一些奇怪的行为。为什么呢? 因为默认情况下,当页面上有足够多的元素时会在触发转换之前先跳转回页面顶部。

怎么解决这个问题?可以为转换效果设置一个超时时间,让它可以在页面滚动到顶部之前执行转换。在应用根目录中打开 gatsby-browser.js 文件,并加入以下代码就行了:

const transitionDelay = 500

exports.shouldUpdateScroll = ({
routerProps: { location },
getSavedScrollPosition,
}) => {
if (location.action === 'PUSH') {
window.setTimeout(() => window.scrollTo(0, 0), transitionDelay)
} else {
const savedPosition = getSavedScrollPosition(location)
window.setTimeout(
() => window.scrollTo(...(savedPosition || [0, 0])),
transitionDelay
)
}
return false
}

在这篇文章中,我们介绍了在 Gatsby 项目中实现页面转换的各种方法。我们研究了如何从头开始设置新的 Gatsby 项目,如何为转换安装必要的依赖项以及如何使用它们来构建页面。

这里讨论的两种方法并不是唯二的选择,也许还有更好的方法或工具来实现大部分功能。你知道的话可以提出来,让大家可以一起学习并构建更好的产品。可以在下面的链接中下载此项目的源代码。在分支之间切换就可以演示转换效果: https://github.com/christiannwamba/Gatsby-page-transitions

英文原文: https://scotch.io/tutorials/animated-page-transitions-in-gatsby-websites

登录查看更多
2

相关内容

React.js(React)是 Facebook 推出的一个用来构建用户界面的 JavaScript 库。

Facebook开源了React,这是该公司用于构建反应式图形界面的JavaScript库,已经应用于构建Instagram网站及 Facebook部分网站。最近出现了AngularJS、MeteorJS 和Polymer中实现的Model-Driven Views等框架,React也顺应了这种趋势。React基于在数据模型之上声明式指定用户界面的理念,用户界面会自动与底层数据保持同步。与前面提及 的框架不同,出于灵活性考虑,React使用JavaScript来构建用户界面,没有选择HTML。Not Rest

【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
190+阅读 · 2020年6月29日
【牛津大学&DeepMind】自监督学习教程,141页ppt
专知会员服务
177+阅读 · 2020年5月29日
Python导论,476页pdf,现代Python计算
专知会员服务
253+阅读 · 2020年5月17日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
专知会员服务
50+阅读 · 2020年1月13日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
173+阅读 · 2020年1月1日
Python奇淫技巧,5个数据可视化工具
机器学习算法与Python学习
7+阅读 · 2019年4月12日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
Python3.7中一种懒加载的方式
Python程序员
3+阅读 · 2018年4月27日
刚开始学编程?这几款小工具能让你事半功倍
Python NLP入门教程
Python开发者
8+阅读 · 2017年11月19日
Python NLP 入门教程
大数据技术
19+阅读 · 2017年10月24日
Directions for Explainable Knowledge-Enabled Systems
Arxiv
26+阅读 · 2020年3月17日
Monocular Plan View Networks for Autonomous Driving
Arxiv
6+阅读 · 2019年5月16日
Music Transformer
Arxiv
5+阅读 · 2018年12月12日
VIP会员
相关资讯
Python奇淫技巧,5个数据可视化工具
机器学习算法与Python学习
7+阅读 · 2019年4月12日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
Python3.7中一种懒加载的方式
Python程序员
3+阅读 · 2018年4月27日
刚开始学编程?这几款小工具能让你事半功倍
Python NLP入门教程
Python开发者
8+阅读 · 2017年11月19日
Python NLP 入门教程
大数据技术
19+阅读 · 2017年10月24日
Top
微信扫码咨询专知VIP会员