├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
└── FUNDING.yml
├── .gitignore
├── .stylelintrc
├── CNAME
├── LICENSE.md
├── README.cn.md
├── README.md
├── components
├── animate
│ ├── demo
│ │ ├── appear.md
│ │ ├── remove.md
│ │ └── simple.md
│ ├── index.en-US.md
│ └── index.zh-CN.md
├── banner-anim
│ ├── demo
│ │ ├── autoplay.md
│ │ ├── bgParallax.md
│ │ ├── customArrowThumb.md
│ │ ├── followMouse.md
│ │ ├── simple.md
│ │ └── video.md
│ ├── index.en-US.md
│ └── index.zh-CN.md
├── queue-anim
│ ├── demo
│ │ ├── basic.md
│ │ ├── change.md
│ │ ├── custom.md
│ │ ├── enter-leave.md
│ │ ├── page.md
│ │ └── simple.md
│ ├── index.en-US.md
│ └── index.zh-CN.md
├── scroll-anim
│ ├── demo
│ │ ├── overPack.md
│ │ ├── parallax-custom.md
│ │ ├── parallax-timeline.md
│ │ └── parallax.md
│ ├── index.en-US.md
│ └── index.zh-CN.md
├── texty
│ ├── demo
│ │ ├── basic.md
│ │ ├── custom.md
│ │ ├── effect.md
│ │ ├── example.md
│ │ └── switch.md
│ ├── index.en-US.md
│ └── index.zh-CN.md
└── tween-one
│ ├── demo
│ ├── bezier.md
│ ├── children.md
│ ├── control.md
│ ├── easingPath.md
│ ├── path.md
│ ├── position.md
│ ├── svgDraw.md
│ ├── svgMorph.md
│ └── timeline.md
│ ├── index.en-US.md
│ └── index.zh-CN.md
├── exhibition
├── demo
│ ├── carousel3d.md
│ ├── detail-switch.md
│ ├── linked-animate.md
│ ├── list-anim.md
│ ├── list-sort.md
│ ├── logo-gather-anim.md
│ ├── pic-details-anim.md
│ ├── snow.md
│ └── table-enter-leave.md
└── js
│ ├── carousel3d.css
│ ├── carousel3d.jsx
│ ├── detail-swich.css
│ ├── detail-swich.jsx
│ ├── linked-animate.css
│ ├── linked-animate.jsx
│ ├── list-anim-animateDemo.css
│ ├── list-anim-animateDemo.jsx
│ ├── list-anim-tweeOneDemo.css
│ ├── list-anim-tweenOneDemo.jsx
│ ├── list-sort.css
│ ├── list-sort.jsx
│ ├── logo-gather-anim.css
│ ├── logo-gather-anim.jsx
│ ├── money.less
│ ├── pic-details-anim.css
│ ├── pic-details-anim.jsx
│ ├── snow.css
│ ├── snow.jsx
│ ├── table-enter-leave.css
│ └── table-enter-leave.jsx
├── language
├── animate-term.md
├── basic.en-US.md
├── basic.zh-CN.md
├── combined.md
├── principle.en-US.md
├── principle.zh-CN.md
├── space.md
├── speed.md
├── transition.en-US.md
└── transition.zh-CN.md
├── package.json
├── renovate.json
├── site
├── bisheng.config.js
└── theme
│ ├── en-US.js
│ ├── index.js
│ ├── static
│ ├── common.less
│ ├── custom.less
│ ├── demo.less
│ ├── demolayout.less
│ ├── exhibition.less
│ ├── footer.less
│ ├── global.less
│ ├── highlight.less
│ ├── home.less
│ ├── index.html
│ ├── logo-demo.less
│ ├── markdown.less
│ ├── page.less
│ ├── responsive.less
│ ├── splicing.less
│ └── style.js
│ ├── template
│ ├── Content
│ │ ├── Article.jsx
│ │ ├── ComponentDoc.jsx
│ │ ├── DemoItem.jsx
│ │ ├── DemoLayout.jsx
│ │ └── Page.jsx
│ ├── Exhibition
│ │ ├── Details.jsx
│ │ └── index.jsx
│ ├── Home
│ │ ├── Banner.jsx
│ │ ├── CodeDemo.jsx
│ │ ├── Demo.jsx
│ │ ├── Page1.jsx
│ │ ├── Page2.jsx
│ │ ├── Page3.jsx
│ │ └── index.jsx
│ ├── Layout
│ │ ├── Footer.jsx
│ │ ├── Header.jsx
│ │ ├── Layout.jsx
│ │ ├── index.jsx
│ │ └── nav.js
│ ├── NotFound.jsx
│ ├── other
│ │ ├── EaseExplain.jsx
│ │ ├── ListSort.jsx
│ │ ├── Principle.jsx
│ │ ├── QueueDemo.jsx
│ │ ├── principle.less
│ │ └── queueDemo.less
│ ├── template.config.js
│ └── utils.jsx
│ └── zh-CN.js
├── theme.js
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | _site
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | const eslintrc = {
2 | extends: ['eslint-config-airbnb'],
3 | env: {
4 | browser: true,
5 | node: true,
6 | jasmine: true,
7 | jest: true,
8 | es6: true,
9 | },
10 | parser: 'babel-eslint',
11 | parserOptions: {
12 | ecmaVersion: 6,
13 | ecmaFeatures: {
14 | jsx: true,
15 | experimentalObjectRestSpread: true,
16 | },
17 | },
18 | plugins: [
19 | 'markdown',
20 | 'react',
21 | 'babel',
22 | ],
23 | rules: {
24 | 'func-names': 0,
25 | 'arrow-body-style': 0,
26 | 'react/sort-comp': 0,
27 | 'react/prop-types': 0,
28 | 'react/jsx-first-prop-new-line': 0,
29 | 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.md'] }],
30 | 'import/extensions': 0,
31 | 'import/no-unresolved': 0,
32 | 'import/no-extraneous-dependencies': 0,
33 | 'prefer-destructuring': 0,
34 | 'no-param-reassign': 0,
35 | 'no-return-assign': 0,
36 | 'max-len': 0,
37 | 'consistent-return': 0,
38 | 'no-redeclare': 0,
39 | 'react/require-extension': 0,
40 | 'jsx-a11y/no-static-element-interactions': 0,
41 | 'jsx-a11y/anchor-has-content': 0,
42 | 'jsx-a11y/click-events-have-key-events': 0,
43 | 'jsx-a11y/no-noninteractive-element-interactions': 0,
44 | 'jsx-a11y/anchor-is-valid': 0,
45 | 'react/no-danger': 0,
46 | 'comma-dangle': ['error', 'always-multiline'],
47 | 'function-paren-newline': 0,
48 | 'object-curly-newline': 0,
49 | 'no-restricted-globals': 0,
50 | 'jsx-a11y/mouse-events-have-key-events': 0,
51 | 'react/jsx-no-target-blank': 0,
52 | 'react/no-find-dom-node': 0,
53 | 'react/no-unescaped-entities': 0,
54 | 'react/prefer-stateless-function': 0,
55 | 'import/no-webpack-loader-syntax': 0,
56 | 'react/forbid-prop-types': 0,
57 | 'react/destructuring-assignment': 0,
58 | 'react/no-access-state-in-setstate': 0,
59 | 'react/require-default-props': 0,
60 | 'jsx-a11y/accessible-emoji': 0,
61 | 'react/static-property-placement': 0,
62 | 'react/jsx-props-no-spreading': 0
63 | },
64 | };
65 |
66 | if (process.env.RUN_ENV === 'DEMO') {
67 | eslintrc.globals = {
68 | React: true,
69 | ReactDOM: true,
70 | mountNode: true,
71 | };
72 |
73 | Object.assign(eslintrc.rules, {
74 | indent: 0,
75 | 'no-console': 0,
76 | 'no-plusplus': 0,
77 | 'eol-last': 0,
78 | 'prefer-rest-params': 0,
79 | 'react/no-multi-comp': 0,
80 | 'jsx-a11y/href-no-hash': 0,
81 | 'import/newline-after-import': 0,
82 | });
83 | }
84 |
85 | module.exports = eslintrc;
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: ant-motion
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | custom: # Replace with a single custom sponsorship URL
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea/
3 | .ipr
4 | .iws
5 | *~
6 | ~*
7 | *.diff
8 | *.patch
9 | *.bak
10 | .DS_Store
11 | Thumbs.db
12 | .project
13 | .*proj
14 | .svn/
15 | *.swp
16 | *.swo
17 | *.pyc
18 | *.pyo
19 | node_modules
20 | dist
21 | psd
22 | old
23 | _site
24 | .vscode
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard",
3 | "rules": {
4 | "comment-empty-line-before": null,
5 | "declaration-empty-line-before": null,
6 | "function-comma-newline-after": null,
7 | "function-name-case": null,
8 | "function-parentheses-newline-inside": null,
9 | "function-max-empty-lines": null,
10 | "function-whitespace-after": null,
11 | "indentation": null,
12 | "number-leading-zero": null,
13 | "number-no-trailing-zeros": null,
14 | "rule-empty-line-before": null,
15 | "selector-combinator-space-after": null,
16 | "selector-list-comma-newline-after": null,
17 | "selector-pseudo-element-colon-notation": null,
18 | "unit-no-unknown": null,
19 | "value-list-max-empty-lines": null,
20 | "no-descending-specificity": null
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | motion.ant.design
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT LICENSE
2 |
3 | Copyright (c) 2015-present Alipay.com, https://www.alipay.com/
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.cn.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | # Ant Motion
8 |
9 | Animation specification and components of Ant Design.
10 |
11 | [国内镜象](http://ant-motion.gitee.io/);
12 |
13 | ## 什么是 Ant Motion ?
14 |
15 | Ant Motion 是 Ant Design 中提炼出来的动效语言。他不仅仅是动效语言,同时也是一套 React 框架动效解决方案,可以帮助开发者,更容易的在项目中使用动效。
16 | 我们提供了单项,组合动画,以及整套解决方案。
17 |
18 |
19 | ## Ant Motion 能做什么 ?
20 |
21 | 通过 React 标签,以简单的配置即可完成想要的动画,可以快速的实现不同组合的动画效果,更好的提高你的工作效率。
22 |
23 | ## 动效 Demo
24 | #### [列表的增删间的动画](http://motion.ant.design/exhibition/demo/list-anim);
25 | #### [详细说明的切换动效](http://motion.ant.design/exhibition/demo/detail-switch);
26 | #### [列表交换位置的动效](http://motion.ant.design/exhibition/demo/list-sort);
27 | #### [图片详细缩略间的切换动效](http://motion.ant.design/exhibition/demo/pic-details-anim);
28 | [>> 查看更多](http://motion.ant.design/exhibition/);
29 |
30 | ## 动效语言
31 | Ant Motion 在界面里主要是来加强体验舒适度、描述层级关系、增加界面活力、反馈与意向等功能性的动效。[详情查看](http://motion.ant.design/language/basic)
32 |
33 | ## 动效组件
34 | #### [rc-tween-one 单元素动效执行组件](http://motion.ant.design/components/tween-one)
35 | 这是个对单个元素标签做动效的组件,可以执行所有样式动画,包括 transform3d,模糊等效果,还可以完成贝塞尔曲线动画,具体参数请参见 [API](http://motion.ant.design/api/tween-one)
36 |
37 | #### [rc-animate 样式进出场组件](http://motion.ant.design/components/animate)
38 | 对单个元素根据状态进行动画显示隐藏,需结合 css 或其它第三方动画类一起使用;具体参数请参见 [API](http://motion.ant.design/api/animate)
39 |
40 | #### [rc-queue-anim 队列进出场组件](http://motion.ant.design/components/queue-anim)
41 | 通过简单的配置对一组元素添加串行的进场动画效果。具体参数请参见 [API](http://motion.ant.design/api/queue-anim)
42 |
43 | #### [rc-scroll-anim 随滚动执行效果组件](http://motion.ant.design/components/scroll-anim)
44 | 通过简单的配置,对页面里的元素添加随滚动条滚动的动画。具体参数请参见 [API](http://motion.ant.design/api/scroll-anim)
45 |
46 | #### [rc-banner-anim banner 切换效果组件](http://motion.ant.design/components/banner-anim)
47 | 通过简单的配置, 就能让你的 banner 动起来。 具体参数请参见 [API](http://motion.ant.design/api/banner-anim)
48 |
49 | ## 首页的解决方案
50 |
51 | Landing 已正式上线,[更多请查看](https://landing.ant.design). 🎉🎉🎉
52 |
53 | 这是以 Ant Motion 的 React 组件遵从 Ant Design 的视觉规范来完成的 demo 页面,可灵活又快速的配置出你想要的首页模板。
54 |
55 | 主要提供了单元素示例与配置完后的整页示例。
56 |
57 | [生成首页在 dva-cli 里运行的例子](https://github.com/ant-motion/ant-motion-dva-cli-example)
58 |
59 | [>> 查看详细](http://t.cn/RIGA89W);
60 |
61 |
62 | ## Develop
63 |
64 | #### 安装
65 |
66 | ```
67 | npm install
68 | ```
69 | #### 启动:
70 |
71 | ```
72 | npm start
73 | ```
74 |
75 | 访问 http://127.0.0.1:8111 。
76 |
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Ant Motion
8 |
9 |
10 |
11 | Animation specification and components of Ant Design.
12 |
13 | [](https://david-dm.org/ant-design/ant-motion)
14 | [](https://david-dm.org/ant-design/ant-motion?type=dev)
15 |
16 |
17 |
18 |
19 |
20 |
21 | ## What is Ant Motion?
22 |
23 | Ant Motion is a motion design specification from Ant Design, and also provide a complete solution with lots of out-of-box animations for your React applications.
24 |
25 | ## What can Ant Motion do?
26 |
27 | - Create neat animations by using React components with a simple configuration.
28 | - Create beautiful landing page with motions by a few steps.
29 |
30 | ## Demos
31 |
32 | - [List animations](http://motion.ant.design/exhibition/demo/list-anim)
33 | - [Detailed explanation of the switching effect](http://motion.ant.design/exhibition/demo/detail-switch)
34 | - [Sortable animated drag and drop list](http://motion.ant.design/exhibition/demo/list-sort)
35 | - [Thumbnail expand with details animation](http://motion.ant.design/exhibition/demo/pic-details-anim)
36 | - [View more](http://motion.ant.design/exhibition/)
37 |
38 | ## Specification
39 |
40 | Ant Motion is an abstraction interface mainly intended to enhance the comfortness in the UX, increase the UI vitality, and also describe the level of relationship among touch feedback, user intentions and other functional effects. [View details](http://motion.ant.design/language/basic)
41 |
42 | ## Animation Components
43 |
44 | - [rc-tween-one](http://motion.ant.design/components/tween-one)
45 |
46 | This is a React wrapper to animate your components. You can perform all of the style animations, including transform3d, fuzzy and other effects, you can also complete the Bezier curve animation. For the specific parameters see the [API](http://motion.ant.design/api/tween-one)
47 |
48 | - [rc-animate](http://motion.ant.design/components/animate)
49 |
50 | On a single element according to the status of animation display hidden, need to combine css or other third-party animation class used together; for the specific parameters see [API](http://motion.ant.design/api/animate)
51 |
52 | - [rc-queue-anim](http://motion.ant.design/components/queue-anim)
53 |
54 | Add a serial rendering approach to a group of elements. Refer to the [API](http://motion.ant.design/api/queue-anim) for the specific parameters.
55 |
56 | - [rc-scroll-anim](http://motion.ant.design/components/scroll-anim)
57 |
58 | Through a simple configuration, you can add animations which follow the scollbar on the elements of the page. Refer to the [API](http://motion.ant.design/api/scroll-anim) for the specific parameters.
59 |
60 | - [rc-banner-anim](http://motion.ant.design/components/banner-anim)
61 |
62 | With a simple configuration, you can set up a modern and professional banner slider. Refer to the [API](http://motion.ant.design/api/banner-anim) for the specific parameters.
63 |
64 | ## Landing page solution
65 |
66 | Landing Formally launched, [more](https://landing.ant.design). 🎉🎉🎉
67 |
68 | This is based on the Ant Motion React components to follow with the design specifications of Ant Design to complete the demo page, you can quickly and flexibly configure the page template you want.
69 |
70 | It provides a single-element example and a full-page example after configuration.
71 |
72 | [ant-motion-dva-cli-example](https://github.com/ant-motion/ant-motion-dva-cli-example)
73 |
74 | [umi-example](https://github.com/ant-motion/landing-umi-example)
75 |
76 | [More details](http://t.cn/RIGA89W)
77 |
78 | ## Develop
79 |
80 | ```
81 | npm install
82 | npm start
83 | ```
84 |
85 | Go to http://localhost:8111
86 |
87 |
--------------------------------------------------------------------------------
/components/animate/demo/appear.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | title:
4 | zh-CN: 开始的进场
5 | en-US: Appear
6 | ---
7 |
8 | ## zh-CN
9 | 开始的进场动画, css 样式查看第一个 demo。
10 |
11 | ## en-US
12 | Appear the opening animation, css style to view the first demo.
13 |
14 | ```jsx
15 | import Animate from 'rc-animate';
16 | import Button from 'antd/lib/button';
17 | class Test extends React.Component{
18 | constructor() {
19 | super(...arguments);
20 | this.state = {
21 | show: true,
22 | };
23 | [
24 | 'onClick',
25 | ].forEach((method) => this[method] = this[method].bind(this));
26 | }
27 |
28 | onClick(){
29 | this.setState({
30 | show: !this.state.show,
31 | });
32 | }
33 |
34 | render(){
35 | return (
36 |
37 |
38 | Switch
39 |
40 |
44 | {this.state.show ?
45 |
: null}
46 |
47 |
48 | );
49 | }
50 | }
51 | ReactDOM.render( , mountNode);
52 | ```
53 |
--------------------------------------------------------------------------------
/components/animate/demo/remove.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 删除子级
5 | en-US: Remove Child
6 | ---
7 |
8 | ## zh-CN
9 |
10 | 动画出场后将子级删除掉。
11 |
12 | ## en-US
13 | The child is deleted after the animation leave.
14 |
15 |
16 | ```jsx
17 | import Animate from 'rc-animate';
18 | import Button from 'antd/lib/button';
19 | class Test extends React.Component{
20 | constructor() {
21 | super(...arguments);
22 | this.state = {
23 | show: true,
24 | };
25 | [
26 | 'onClick',
27 | ].forEach((method) => this[method] = this[method].bind(this));
28 | }
29 |
30 | onClick(){
31 | this.setState({
32 | show: !this.state.show,
33 | });
34 | }
35 |
36 | render(){
37 | return (
38 |
39 |
40 | Switch
41 |
42 |
46 | {
47 | this.state.show ?
48 |
: null}
49 |
50 |
51 | );
52 | }
53 | }
54 | ReactDOM.render( , mountNode);
55 | ```
56 |
--------------------------------------------------------------------------------
/components/animate/demo/simple.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: 简单的例子
5 | en-US: Simple
6 | ---
7 | ## zh-CN
8 | 同时支持进场和离场动画。
9 |
10 | ## en-US
11 | Both enter and leave animations are supported.
12 |
13 | ```jsx
14 | import Animate from 'rc-animate';
15 | import Button from 'antd/lib/button';
16 | const Div = (props) => {
17 | const childrenProps = { ...props };
18 | delete childrenProps.show;
19 | return
;
20 | };
21 | class Test extends React.Component{
22 | constructor() {
23 | super(...arguments);
24 | this.state = {
25 | show: true,
26 | };
27 | [
28 | 'onClick',
29 | ].forEach((method) => this[method] = this[method].bind(this));
30 | }
31 |
32 | onClick(){
33 | this.setState({
34 | show: !this.state.show,
35 | });
36 | }
37 |
38 | render(){
39 | return (
40 |
41 |
42 | Switch
43 |
44 |
48 |
49 |
50 |
51 | );
52 | }
53 | }
54 | ReactDOM.render( , mountNode);
55 | ```
56 |
57 | ```css
58 | .fade-enter {
59 | opacity: 0;
60 | animation-duration: .5s;
61 | animation-fill-mode: both;
62 | animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
63 | animation-play-state: paused;
64 | }
65 |
66 | .fade-appear {
67 | opacity: 0;
68 | animation-duration: .5s;
69 | animation-fill-mode: both;
70 | animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
71 | animation-play-state: paused;
72 | }
73 |
74 | .fade-leave {
75 | animation-duration: .5s;
76 | animation-fill-mode: both;
77 | animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
78 | animation-play-state: paused;
79 | }
80 |
81 | .fade-enter.fade-enter-active {
82 | animation-name: fadeIn;
83 | animation-play-state: running;
84 | }
85 |
86 | .fade-appear.fade-appear-active {
87 | animation-name: fadeIn;
88 | animation-play-state: running;
89 | }
90 |
91 | .fade-leave.fade-leave-active {
92 | animation-name: fadeOut;
93 | animation-play-state: running;
94 | }
95 |
96 | @keyframes fadeIn {
97 | 0% {
98 | opacity: 0;
99 | }
100 | 100% {
101 | opacity: 1;
102 | }
103 | }
104 |
105 | @keyframes fadeOut {
106 | 0% {
107 | opacity: 1;
108 | }
109 | 100% {
110 | opacity: 0;
111 | }
112 | }
113 |
114 | ```
115 |
--------------------------------------------------------------------------------
/components/animate/index.en-US.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title: Animate
4 | ---
5 |
6 | Animate the individual elements according to the state, and use them together with css or other third-party animation classes; specific ref [API](/api/animate)
7 |
8 | ## When To Use
9 |
10 | - When the element state is switched;
11 |
12 | ---
13 |
14 | ## How To Use
15 |
16 | ### Install
17 |
18 | ```bash
19 | $ npm install rc-animate --save
20 | ```
21 |
22 | ### Usage
23 |
24 | ```jsx
25 | var Animate = require('rc-animate');
26 | var ReactDOM = require('react-dom');
27 | ReactDOM.render((
28 |
29 | {show ? demo
: null}
30 |
31 | ), container);
32 | ```
33 | > [Detailed use](https://github.com/react-component/animate/blob/master/docs/zh-cn/intro.md)
34 |
35 | ## API
36 |
37 | ### props
38 |
39 | | name | type | default | description |
40 | |-----------|----------|------------|-------------------|
41 | | showProp | String | null | using prop for show and hide. [demo](http://react-component.github.io/animate/examples/hide-todo.html) |
42 | | exclusive | Boolean | false | whether allow only one set of animations(enter and leave) at the same time. |
43 | | transitionName | String | null | specify corresponding css, see ReactCSSTransitionGroup |
44 | | transitionAppear | Boolean | false | whether support transition appear animate |
45 | | transitionEnter | Boolean | true | whether support transition enter animate |
46 | | transitionLeave | Boolean | true | whether support transition leave animate |
47 | | onEnd | Func | true | animation end callback, callBack(key: String, exists: Boolean); |
48 | | animation | Object | {} | to animate with js. see animation format below. |
49 | | component | React.Element/String | `span` | wrap dom node or component for children. set to '' if you do not wrap for only one child |
50 | | componentProps | Object | {} | extra props that will be passed to component |
51 |
52 | > `animation` case to see [demo](http://react-component.github.io/animate/)
53 |
--------------------------------------------------------------------------------
/components/animate/index.zh-CN.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: Css样式动画
5 | en-US: Animate
6 | ---
7 |
8 | 对单个元素根据状态进行动画显示隐藏,需结合 css 或其它第三方动画类一起使用;具体参数请参见 [API](/api/animate)
9 |
10 | ## 何时使用
11 |
12 | - 对单个元素状态切换时进行动画显示隐藏;
13 |
14 | ---
15 |
16 | ## 怎么使用
17 |
18 | ### 安装
19 |
20 | ```bash
21 | $ npm install rc-animate --save
22 | ```
23 |
24 | ### 使用
25 |
26 | ```jsx
27 | var Animate = require('rc-animate');
28 | var ReactDOM = require('react-dom');
29 | ReactDOM.render((
30 |
31 | {show ? 示例
: null}
32 |
33 | ), container);
34 | ```
35 | > [查看详细使用](https://github.com/react-component/animate/blob/master/docs/zh-cn/intro.md)
36 |
37 | ## API
38 |
39 | ### props
40 |
41 | | 参数 | 类型 | 默认 | 说明 |
42 | |-----------|----------|------------|-------------------|
43 | | showProp | String | null | 子级动画的类型,显示或隐藏。 [demo](http://react-component.github.io/animate/examples/hide-todo.html) |
44 | | exclusive | Boolean | false | 同时触发动画时,是否只允许只播放一个动画 |
45 | | transitionName | String | null | css 样式的名称, `fade`: enter: `fade-enter fade-enter-active` leave: `fade-leave fade-leave-active` |
46 | | transitionAppear | Boolean | false | 是否支持开始出现的动画 |
47 | | transitionEnter | Boolean | true | 是否支持进场的动画, 出场后的进场 |
48 | | transitionLeave | Boolean | true | 是否支持出场的动画 |
49 | | onEnd | Func | true | 动画结束后的回调, callBack(key: String, exists: Boolean); |
50 | | animation | Object | {} | 使用第三方动画类来执行动画 |
51 | | component | React.Element/String | `span` | 需要替换的标签 |
52 |
53 | > animation 的动画案例去查看 react-component 里的 simple-animation, [查看demo](http://react-component.github.io/animate/)
54 |
--------------------------------------------------------------------------------
/components/banner-anim/demo/autoplay.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 自动播放
5 | en-US: Auto Play
6 | ---
7 |
8 | ## zh-CN
9 | 自动播放示例。
10 |
11 | ## en-US
12 |
13 | autoPlay example.
14 |
15 | ````jsx
16 | import BannerAnim, { Element } from 'rc-banner-anim';
17 | import TweenOne from 'rc-tween-one';
18 | import 'rc-banner-anim/assets/index.css';
19 | const BgElement = Element.BgElement;
20 | class Demo extends React.Component {
21 | render(){
22 | return (
23 |
24 |
28 |
35 |
36 | Ant Motion Banner
37 |
38 |
41 | The Fast Way Use Animation In React
42 |
43 |
44 |
48 |
55 |
56 | Ant Motion Banner
57 |
58 |
61 | The Fast Way Use Animation In React
62 |
63 |
64 | );
65 | }
66 | }
67 | ReactDOM.render(
68 |
69 | , mountNode);
70 | ````
71 |
72 |
73 |
--------------------------------------------------------------------------------
/components/banner-anim/demo/bgParallax.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 4
3 | title:
4 | zh-CN: 背景随滚动下滑
5 | en-US: Bg Follows The Scroll Down
6 | hidden: true
7 | ---
8 |
9 | 背景随滚动下滑(待优化)。
10 |
11 | ````jsx
12 | import BannerAnim, { Element } from 'rc-banner-anim';
13 | import TweenOne from 'rc-tween-one';
14 | import 'rc-banner-anim/assets/index.css';
15 | class Demo extends React.Component {
16 | render(){
17 | return (
18 |
19 |
23 |
32 | Ant Motion Demo
33 | Image source from the network Demo, please upload pictures to replace.Image source
34 |
35 |
39 |
48 | Ant Motion Demo
49 | Image source from the network Demo, please upload pictures to replace.Image source
50 |
51 | );
52 | }
53 | }
54 | ReactDOM.render(
55 |
56 | , mountNode);
57 | ````
58 |
59 | ````css
60 | .banner-user-elem{
61 | height: 400px;
62 | text-align: center;
63 | color: #fff;
64 | position: relative;
65 | overflow: hidden;
66 | }
67 | .banner-user-elem .banner-user-title{
68 | font-size: 22px;
69 | top: 40%;
70 | }
71 | .banner-user-elem .banner-user-text{
72 | top: 40%;
73 | }
74 | ````
75 |
--------------------------------------------------------------------------------
/components/banner-anim/demo/followMouse.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 5
3 | title:
4 | zh-CN: 随鼠标摆动
5 | en-US: Follow The Mouse
6 | ---
7 |
8 | ## zh-CN
9 | 跟随鼠标左右摆动。
10 |
11 | ## en-US
12 | Follow the mouse to swing.
13 |
14 | ````jsx
15 | import BannerAnim, { Element } from 'rc-banner-anim';
16 | import TweenOne from 'rc-tween-one';
17 | import 'rc-banner-anim/assets/index.css';
18 | const BgElement = Element.BgElement;
19 | class Demo extends React.Component {
20 | render() {
21 | return (
22 |
23 |
34 |
42 |
46 | Ant Motion Banner
47 |
48 |
52 | The Fast Way Use Animation In React
53 |
54 |
55 |
58 |
65 |
66 | Ant Motion Banner
67 |
68 |
71 | The Fast Way Use Animation In React
72 |
73 |
74 |
75 | );
76 | }
77 | }
78 | ReactDOM.render(
79 |
80 | , mountNode);
81 | ````
82 |
--------------------------------------------------------------------------------
/components/banner-anim/demo/simple.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: 简单的例子
5 | en-US: Simple
6 | cols: 1
7 | ---
8 |
9 | ## zh-CN
10 | 最简单的进场例子。
11 |
12 | ## en-US
13 | The simplest example.
14 |
15 | ````jsx
16 | import BannerAnim, { Element } from 'rc-banner-anim';
17 | import TweenOne from 'rc-tween-one';
18 | import 'rc-banner-anim/assets/index.css';
19 | const BgElement = Element.BgElement;
20 | class Demo extends React.Component {
21 | render(){
22 | return (
23 |
24 |
28 |
35 |
36 | Ant Motion Banner
37 |
38 |
41 | The Fast Way Use Animation In React
42 |
43 |
44 |
48 |
55 |
56 | Ant Motion Banner
57 |
58 |
61 | The Fast Way Use Animation In React
62 |
63 |
64 | );
65 | }
66 | }
67 | ReactDOM.render(
68 |
69 | , mountNode);
70 | ````
71 | ```css
72 | /* 通用样式, 下例 demo 单独使用都需要这块样式 */
73 | .banner-user{
74 | height: 220px;
75 | }
76 | .banner-user-elem{
77 | text-align: center;
78 | color: #fff;
79 | position: relative;
80 | overflow: hidden;
81 | }
82 | .banner-user-elem .banner-user-title{
83 | font-size: 32px;
84 | top: 40%;
85 | }
86 | .banner-user-elem .banner-user-text{
87 | top: 40%;
88 | }
89 | .banner-anim-elem .bg{
90 | width: 100%;
91 | height: 100%;
92 | position: absolute;
93 | top: 0;
94 | left: 0;
95 | overflow: hidden;
96 | }
97 | ```
--------------------------------------------------------------------------------
/components/banner-anim/demo/video.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: Video 背景
5 | en-US: Video Bg
6 | hidden: true
7 | ---
8 |
9 | ## zh-CN
10 |
11 | 用 video 作为背景时。
12 |
13 | ## en-US
14 |
15 | When using video as the background.
16 |
17 | ````jsx
18 | import BannerAnim, { Element } from 'rc-banner-anim';
19 | import TweenOne from 'rc-tween-one';
20 | import 'rc-banner-anim/assets/index.css';
21 | class Demo extends React.Component {
22 | render() {
23 | return (
24 |
25 |
30 | Ant Motion Demo
31 | Image source from the network Demo, please upload pictures to replace.Image source
32 |
33 |
37 | Ant Motion Demo
38 | Image source from the network Demo, please upload pictures to replace.Image source
39 |
40 |
44 | Ant Motion Demo
45 | Image source from the network Demo, please upload pictures to replace.Image source
46 |
47 |
48 | );
49 | }
50 | }
51 | ReactDOM.render(
52 |
53 | , mountNode);
54 | ````
55 |
--------------------------------------------------------------------------------
/components/queue-anim/demo/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 进场和离场
5 | en-US: Enter And Leave
6 |
7 | ---
8 |
9 | ## zh-CN
10 | 同时支持进场和离场动画。
11 |
12 | ## en-US
13 | Both enter and leave animations are supported.
14 |
15 | ````jsx
16 | import Button from 'antd/lib/button';
17 | import QueueAnim from 'rc-queue-anim';
18 |
19 | class Test extends React.Component{
20 | state = {
21 | show: true
22 | };
23 | onClick = () => {
24 | this.setState({
25 | show: !this.state.show
26 | });
27 | }
28 | render() {
29 | return (
30 |
31 |
32 | Switch
33 |
34 |
35 | {this.state.show ? [
36 | ,
43 |
50 | ] : null}
51 |
52 |
53 | );
54 | }
55 | };
56 |
57 | ReactDOM.render( , mountNode);
58 | ````
59 |
--------------------------------------------------------------------------------
/components/queue-anim/demo/change.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: 添加与删除
5 | en-US: Add And Remove
6 | ---
7 | ## zh-CN
8 | 场景里有增加或删除条目时也会触发动画。
9 |
10 | ## en-US
11 | Animations are also triggered when there are additions or deletions to the scene.
12 |
13 | ````jsx
14 | import Button from 'antd/lib/button';
15 | import QueueAnim from 'rc-queue-anim';
16 |
17 | class Test extends React.Component{
18 | state = {
19 | show: true,
20 | items: [
21 | ,
22 | ,
23 |
24 | ],
25 | };
26 | onClick = () => {
27 | this.setState({
28 | show: !this.state.show,
29 | });
30 | }
31 | onAdd = () => {
32 | let items = this.state.items;
33 | items.push( );
34 | this.setState({
35 | show: true,
36 | items,
37 | });
38 | }
39 | onRemove = () => {
40 | let items = this.state.items;
41 | items.splice(items.length - 1, 1);
42 | this.setState({
43 | show: true,
44 | items,
45 | });
46 | }
47 | render() {
48 | return (
49 |
50 |
51 | Switch
52 | Add
53 | Remove
54 |
55 |
56 |
63 |
64 |
65 | {this.state.show ? this.state.items : null}
66 |
67 |
68 |
69 |
70 | );
71 | }
72 | };
73 |
74 | ReactDOM.render( , mountNode);
75 | ````
76 |
--------------------------------------------------------------------------------
/components/queue-anim/demo/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 4
3 | title:
4 | zh-CN: 自定义动画进出场
5 | en-US: Custom Animation
6 | ---
7 |
8 | ## zh-CN
9 | 通过 `animConfig` 来自定义动画进出场。
10 |
11 | ## en-US
12 |
13 | Customize into and out of the animation with `animConfig`.
14 |
15 | ````jsx
16 | import Button from 'antd/lib/button';
17 | import QueueAnim from 'rc-queue-anim';
18 |
19 | class Test extends React.Component{
20 | state = {
21 | show: true,
22 | };
23 | onClick = () => {
24 | this.setState({
25 | show: !this.state.show,
26 | });
27 | }
28 | render() {
29 | return (
30 |
31 |
32 | Switch
33 |
34 |
39 | {this.state.show ? [
40 | ,
47 |
54 | ] : null}
55 |
56 |
57 | );
58 | }
59 | };
60 |
61 | ReactDOM.render( , mountNode);
62 | ````
63 |
--------------------------------------------------------------------------------
/components/queue-anim/demo/enter-leave.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | title:
4 | zh-CN: 属性设置
5 | en-US: Property Settings
6 | ---
7 |
8 | ## zh-CN
9 |
10 | 通过把属性设置一个数组来分别表示进出场的效果,`type`、`animConfig`、`delay`、`duration`、`interval`、`ease` 等属性均支持配置为数组。
11 |
12 | ## en-US
13 | By setting properties to represent the animation of entering and leaving, `type`, `animConfig`, `delay`, `duration`, `interval`, `ease` etc attributes support arrays.
14 |
15 | ````jsx
16 | import Button from 'antd/lib/button';
17 | import QueueAnim from 'rc-queue-anim';
18 |
19 | class Test extends React.Component{
20 | state = {
21 | show: true
22 | };
23 | onClick = () => {
24 | this.setState({
25 | show: !this.state.show
26 | });
27 | }
28 | render() {
29 | return (
30 |
31 |
32 | Switch
33 |
34 |
38 | {this.state.show ? [
39 | ,
46 |
53 | ] : null}
54 |
55 |
56 | );
57 | }
58 | };
59 |
60 | ReactDOM.render( , mountNode);
61 | ````
62 |
--------------------------------------------------------------------------------
/components/queue-anim/demo/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 5
3 | title:
4 | zh-CN: 一个复杂些的例子
5 | en-US: Complex Example
6 | ---
7 | ## zh-CN
8 | 模拟一个完整的页面。
9 |
10 | ## en-US
11 |
12 | Simulate a complete page.
13 |
14 | ````jsx
15 | import Button from 'antd/lib/button';
16 | import QueueAnim from 'rc-queue-anim';
17 |
18 | class Test extends React.Component{
19 | state = {
20 | show: true
21 | };
22 | onClick = () => {
23 | this.setState({
24 | show: !this.state.show
25 | });
26 | }
27 | render() {
28 | return (
29 |
30 |
31 | Switch
32 |
33 |
34 | {this.state.show ? [
35 |
36 |
37 |
38 |
39 |
40 |
45 |
,
46 | ,
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | ,
66 |
,
67 | ] : null}
68 |
69 |
70 | );
71 | }
72 | };
73 |
74 | ReactDOM.render( , mountNode);
75 | ````
76 |
--------------------------------------------------------------------------------
/components/queue-anim/demo/simple.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: 简单的例子
5 | en-US: Simple example
6 | ---
7 |
8 | ## zh-CN
9 | 最简单的进场例子。
10 |
11 | ## en-US
12 | The simplest example of entry.
13 |
14 | ````jsx
15 | import QueueAnim from 'rc-queue-anim';
16 |
17 | ReactDOM.render(
18 |
19 | Queue Demo
20 | Queue Demo
21 | Queue Demo
22 | Queue Demo
23 |
24 | , mountNode);
25 | ````
26 |
--------------------------------------------------------------------------------
/components/queue-anim/index.en-US.md:
--------------------------------------------------------------------------------
1 | ---
2 | cols: 2
3 | order: 2
4 | vertical: true
5 | title: QueueAnim
6 | ---
7 |
8 | Add queue animation to a set of elements with a simple configuration. See the specific ref [API](/api/queue-anim)
9 |
10 | ## When To Use
11 |
12 | - The transition from content A to content B can effectively attract users' attention, highlight the visual center, and improve the overall visual effect.。
13 |
14 | - Small information elements arranged or a lot of blocky cases, entering according to a certain path level, differentiate the dimension hierarchy, make page transitions smoother and more comfortable, improve overall visuals and product texture
15 |
16 | - Ideal for homepages, as well as page transitions for single-page apps.
17 |
18 | ---
19 |
20 | ## How To Use
21 |
22 | ### Install
23 |
24 | ```bash
25 | $ npm install rc-queue-anim --save
26 | ```
27 | ### Usage
28 |
29 | ```jsx
30 | import QueueAnim from 'rc-queue-anim';
31 | ReactDOM.render(
32 | Queue entering
33 | Queue entering
34 | Queue entering
35 | Queue entering
36 | , mountNode);
37 | ```
38 | > Each subtag must have a key, and if no key is set, no animation will be performed.
39 |
40 | ## API
41 |
42 | > v1.2.0 animConfig add [timeline](http://react-component.github.io/queue-anim/examples/timeline.html)
43 |
44 | | name | type | default | description |
45 | |------------|----------------|---------|----------------|
46 | | type | string / array | `right` | Animation type `alpha` `left` `right` `top` `bottom` `scale` `scaleBig` `scaleX` `scaleY`|
47 | | animConfig | object / array | null | Custom config, See below for more details [animConfig](#animConfig) |
48 | | delay | number / array | 0 | Default unit: `ms`, delay of animation |
49 | | duration | number / array | 450 | Default unit: `ms`, duration of animation |
50 | | interval | number / array | 100 | Default unit: `ms`, interval of duration |
51 | | leaveReverse | boolean | false | reverse animation order at leave |
52 | | ease | string / array | `easeOutQuart` | animation easing config like 'ease', ['easeIn', 'easeOut'], [[.42,0,.58,1], [.42,0,.58,1]], [more](http://julian.com/research/velocity/#easing) |
53 | | appear | boolean | true | whether support appear anim |
54 | | animatingClassName | array | `['queue-anim-entering', 'queue-anim-leaving']` | className to every element of animating |
55 | | component | React.Element/string | `div` | QueueAnim replaced tag name |
56 | | componentProps | object | {} | Replaced component props |
57 | | forcedReplay | boolean | false | Whether to forcibly replay the animation, for example: trigger the `leave` when the `enter`, and immediately execute the `enter`. |
58 | | onEnd | func | null | animation end callback({ key, type }); type: `enter` or `leave` |
59 |
60 | > Above props support array format, like \['left', 'top'\], `top` is leave config.
61 |
62 | ### animConfig
63 |
64 | **Data fall into three categories:**
65 |
66 | - Custom set start: `{ opacity:[1, 0] }` ;
67 | default;
68 | type: `{ opacity: Array }`;
69 | leave automatic reverse: `{ opacity: Array }`;
70 |
71 |
72 |
73 | - Custom: `{ opacity: 0 }`;
74 | Start position is not set.
75 |
76 |
77 |
78 | - Array: `[{ opacity:[1, 0] }, { opacity:[1, 0] }]`;
79 | type: `[{ opacity: Array }, { opacity: Array}]`
--------------------------------------------------------------------------------
/components/queue-anim/index.zh-CN.md:
--------------------------------------------------------------------------------
1 | ---
2 | cols: 2
3 | order: 2
4 | vertical: true
5 | title:
6 | zh-CN: 进出场动画
7 | en-US: QueueAnim
8 | ---
9 |
10 | 通过简单的配置对一组元素添加串行的进场动画效果。具体参数请参见 [API](/api/queue-anim)
11 |
12 | ## 何时使用
13 |
14 | - 从内容 A 到内容B的转变过程时能有效的吸引用户注意力,突出视觉中心,提高整体视觉效果。
15 |
16 | - 小的信息元素排布或块状较多的情况下,根据一定的路径层次依次进场,区分维度层级,来突显量级,使页面转场更加流畅和舒适,提高整体视觉效果和产品的质感。
17 |
18 | - 特别适合首页和需要视觉展示效果的宣传页,以及单页应用的切换页面动效。
19 |
20 | ---
21 |
22 | ## 怎么使用
23 | ### 安装
24 | ```bash
25 | $ npm install rc-queue-anim --save
26 | ```
27 | ### 使用
28 | ```jsx
29 | import QueueAnim from 'rc-queue-anim';
30 | ReactDOM.render(
31 | 依次进场
32 | 依次进场
33 | 依次进场
34 | 依次进场
35 | , mountNode);
36 | ```
37 | > 每个子标签必须带 key,如果未设置 key 将不执行动画。
38 |
39 | ## API
40 |
41 | > v1.2.0 animConfig 增加 [timeline](http://react-component.github.io/queue-anim/examples/timeline.html)
42 |
43 | |参数 |类型 |默认 |详细 |
44 | |------------|----------------|---------|----------------|
45 | | type | string / array | `right` | 动画内置参数 `alpha` `left` `right` `top` `bottom` `scale` `scaleBig` `scaleX` `scaleY`|
46 | | animConfig | object / array | null | 配置动画参数 如 `{ opacity:[1, 0] }` 参数为: `{ opacity: Array }` 出场则相反: `{ opacity: Array }`; 详细说明查看下面的 [animConfig](#animConfig) |
47 | | delay | number / array | 0 | 整个动画的延时,以毫秒为单位 |
48 | | duration | number / array | 450 | 每个动画的时间,以毫秒为单位 |
49 | | interval | number / array | 100 | 每个动画的间隔时间,以毫秒为单位 |
50 | | leaveReverse | boolean | false | 出场时是否倒放,从最后一个 dom 开始往上播放 |
51 | | ease | string / array | `easeOutQuart` | 动画的缓动函数,[查看详细](http://julian.com/research/velocity/#easing) |
52 | | appear | boolean | true | 开始进入时是否有动画 |
53 | | animatingClassName | array | `['queue-anim-entering', 'queue-anim-leaving']` | 进出场动画进行中的类名 |
54 | | component | React.Element/string | `div` | QueueAnim 替换的标签名 |
55 | | componentProps | object | {} | 组件的 props |
56 | | forcedReplay | boolean | false | 是否强制重放动画,比如:在出场动画时触发了进场动画,立即执行进场动画 |
57 | | onEnd | func | null | 动画结束后回调, callback({ key, type }); type 为 `enter` 或 `leave` |
58 |
59 | > 当以上数据类型为 Array 时,`['left', 'top']` 第一个为进场动画属性, 第二个为离场属性。
60 |
61 | ### animConfig
62 |
63 | **数据分为三种:**
64 |
65 | - 自定义设定开始样式: `{ opacity:[1, 0] }` ;
66 | 默认数据类型;
67 | 参数类型: `{ opacity: Array }`;
68 | 出场自动反向: `{ opacity: Array }`;
69 |
70 |
71 |
72 | - 自定义样式: `{ opacity: 0 }`;
73 | 不设置开始位置。
74 |
75 |
76 |
77 |
78 | - 自定义数组进出场样式: `[{ opacity:[1, 0] }, { opacity:[1, 0] }]`;
79 | 数组型;
80 | 参数类型: `[{ opacity: Array }, { opacity: Array}]`
--------------------------------------------------------------------------------
/components/scroll-anim/demo/overPack.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: OverPack 例子
5 | en-US: OverPack
6 | ---
7 |
8 | ## zh-CN
9 | 设置了在屏幕下方 50% 时开始播放动画,子级可支持 `rc-queue-anim` `rc-animate` `rc-tween-one`。
10 |
11 | ## en-US
12 | Set to start playing the animation at 50% below the screen, the child can support `rc-queue-anim` `rc-animate` `rc-tween-one`.
13 |
14 | ```jsx
15 | import { OverPack } from 'rc-scroll-anim';
16 | import TweenOne from 'rc-tween-one';
17 | import QueueAnim from 'rc-queue-anim';
18 |
19 | class Demo extends React.Component {
20 | render() {
21 | return (
22 |
23 |
27 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | }
41 | }
42 | ReactDOM.render( , mountNode);
43 | ```
44 |
--------------------------------------------------------------------------------
/components/scroll-anim/demo/parallax-custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 自定义 Parallax 的 playScale
5 | en-US: Custom Parallax playScale
6 | ---
7 |
8 | ## zh-CN
9 | 自定义 playScale,在屏幕中间开始播放,到 80% 结束动画。
10 |
11 | ## en-US
12 | Customize playScale, start playing in the middle of the screen, and end the animation at 80%.
13 |
14 | ```jsx
15 | import { Parallax } from 'rc-scroll-anim';
16 |
17 | class Demo extends React.Component {
18 | render() {
19 | return (
20 |
27 | );
28 | }
29 | }
30 | ReactDOM.render( , mountNode);
31 | ```
32 |
--------------------------------------------------------------------------------
/components/scroll-anim/demo/parallax-timeline.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | title:
4 | zh-CN: Parallax 的时间轴动画
5 | en-US: Parallax Timeline
6 | ---
7 | ## zh-CN
8 | 可配置多个动画,然后再配合 playScale 完成滚动动画
9 | ## en-US
10 | Multiple animations can be configured and then played with playScale.
11 |
12 | ```jsx
13 | import { Parallax } from 'rc-scroll-anim';
14 |
15 | class Demo extends React.Component {
16 | render() {
17 | return (
18 |
29 | );
30 | }
31 | }
32 | ReactDOM.render( , mountNode);
33 | ```
34 |
--------------------------------------------------------------------------------
/components/scroll-anim/demo/parallax.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: Parallax 示例
5 | en-US: Parallax
6 | ---
7 |
8 | ## zh-CN
9 | 随滚动来播放动画
10 |
11 | ## en-US
12 | Follow the scroll to play the animation.
13 |
14 | ```jsx
15 | import { Parallax } from 'rc-scroll-anim';
16 |
17 | class Demo extends React.Component {
18 | render() {
19 | return (
20 |
37 | );
38 | }
39 | }
40 | ReactDOM.render( , mountNode);
41 | ```
42 |
--------------------------------------------------------------------------------
/components/texty/demo/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: 基本效果
5 | en-US: Basic
6 | ---
7 |
8 | ## zh-CN
9 | 默认文字效果
10 |
11 | ## en-US
12 | Default text effect.
13 |
14 |
21 |
22 | ```jsx
23 | import Texty from 'rc-texty';
24 | import 'rc-texty/assets/index.css';
25 |
26 | ReactDOM.render((
27 |
28 | Ant Motion
29 |
30 | ), mountNode);
31 | ```
--------------------------------------------------------------------------------
/components/texty/demo/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: 自定义
5 | en-US: Custom
6 | ---
7 | ## zh-CN
8 | 自定义动画效果
9 |
10 | ## en-US
11 | Custom animation.
12 |
13 | ```jsx
14 | import Texty from 'rc-texty';
15 | import Button from 'antd/lib/button';
16 | import 'rc-texty/assets/index.css';
17 |
18 | class Demo extends React.Component{
19 | state = {
20 | show: true
21 | };
22 | getEnter = (e) => {
23 | switch (e.index) {
24 | case 0:
25 | return {
26 | rotate: 90,
27 | opacity: 0,
28 | y: -60,
29 | };
30 | case 10:
31 | case 1:
32 | return {
33 | y: -60,
34 | x: -10,
35 | opacity: 0,
36 | };
37 | case 9:
38 | case 2:
39 | return {
40 | y: -60,
41 | x: 20,
42 | opacity: 0,
43 | };
44 | case 3:
45 | return {
46 | y: 60,
47 | opacity: 0,
48 | };
49 | case 8:
50 | case 4:
51 | return {
52 | x: 30,
53 | opacity: 0,
54 | };
55 | case 5:
56 | return {
57 | enter: [
58 | {
59 | scale: 2,
60 | opacity: 0,
61 | type: 'set',
62 | },
63 | { scale: 1.2, opacity: 1, duration: 300 },
64 | { scale: 0.9, duration: 200 },
65 | { scale: 1.05, duration: 150 },
66 | { scale: 1, duration: 100 },
67 | ],
68 | leave: {
69 | opacity: 0, scale: 0,
70 | },
71 | };
72 | case 6:
73 | return {
74 | scale: 0.8,
75 | x: 30,
76 | y: -10,
77 | opacity: 0,
78 | };
79 | case 7:
80 | return {
81 | scale: 0.8,
82 | x: 30,
83 | y: 10,
84 | opacity: 0,
85 | };
86 | default:
87 | return {
88 | opacity: 0,
89 | };
90 | }
91 | }
92 | onClick = () => {
93 | this.setState({
94 | show: !this.state.show
95 | });
96 | }
97 | render(){
98 | return (
99 |
100 |
101 | Switch
102 |
103 |
{this.state.show && 'Ant Motion'}
104 |
105 | );
106 | }
107 | }
108 | ReactDOM.render( , mountNode);
109 | ```
--------------------------------------------------------------------------------
/components/texty/demo/effect.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: 内置效果
5 | en-US: Type
6 | ---
7 |
8 | ## zh-CN
9 | 内置效果
10 |
11 | ## en-US
12 | Built-in type.
13 |
14 | ```jsx
15 | import Texty from 'rc-texty';
16 | import Button from 'antd/lib/button';
17 | import Select from 'antd/lib/select';
18 | import 'rc-texty/assets/index.css';
19 |
20 | import animType from 'rc-texty/lib/animTypes';
21 |
22 | const { Option } = Select;
23 |
24 | class Demo extends React.Component{
25 | state = {
26 | show: true,
27 | mode: 'smooth',
28 | type: 'left',
29 | };
30 | onClick = () => {
31 | this.setState({
32 | show: !this.state.show
33 | });
34 | }
35 | onChange = (type) => {
36 | this.setState({
37 | type,
38 | });
39 | }
40 |
41 | onModeChange = (mode) => {
42 | this.setState({
43 | mode,
44 | });
45 | }
46 |
47 | render(){
48 | return (
49 |
50 |
51 | Switch
52 |
53 |
54 | type:
55 |
56 | {Object.keys(animType).map(key => ({key} ))}
57 |
58 | mode:
59 |
60 | {['smooth', 'reverse', 'random', 'sync'].map(key => ({key} ))}
61 |
62 |
63 |
67 | {this.state.show && 'Ant Motion'}
68 |
69 |
70 | );
71 | }
72 | }
73 | ReactDOM.render( , mountNode);
74 | ```
--------------------------------------------------------------------------------
/components/texty/demo/switch.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 文字切换
5 | en-US: Switch
6 | ---
7 |
8 | ## zh-CN
9 | 文字切换效果
10 |
11 | ## en-US
12 | Text switching.
13 |
14 | ```jsx
15 | import Texty from 'rc-texty';
16 | import Button from 'antd/lib/button';
17 | import 'rc-texty/assets/index.css';
18 |
19 | class Demo extends React.Component{
20 | state = {
21 | show: true
22 | };
23 | onClick = () => {
24 | this.setState({
25 | show: !this.state.show
26 | });
27 | }
28 | render(){
29 | return (
30 |
31 |
32 | Switch
33 |
34 |
{this.state.show && 'Ant Motion'}
35 |
36 | );
37 | }
38 | }
39 | ReactDOM.render( , mountNode);
40 | ```
--------------------------------------------------------------------------------
/components/texty/index.en-US.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title: TextyAnim
4 | ---
5 |
6 | A component for entering and leaving animations for text titles, providing non-rich animation, or configuring different effects according to your own needs. See the specific ref [API](/api/texty);
7 |
8 | ## When To Use
9 |
10 | - Used in the animation elements of the enter and leave, for interval animation of the title or body text.
11 | - An animation of the enter of each word at different times.
12 |
13 | ---
14 | ## How To Use
15 |
16 | ### Install
17 |
18 | ```bash
19 | $ npm install rc-texty --save
20 | ```
21 | ### Usage
22 |
23 | ```jsx
24 | import Texty from 'rc-texty';
25 | ReactDOM.render(text , mountNode);
26 | ```
27 |
28 |
29 | ## API
30 |
31 | | name | type | default | description |
32 | | --------- | -------------- | -------- | ----------------------------------------- |
33 | | className | string | `null` | class name. |
34 | | prefixCls | string | `texty` | prefix class. |
35 | | type | string | `top` | animation type, `left` \| `right` \| `top` \| `bottom` \|`alpha` \| `scale` \| `scaleX` \| `scaleBig` \| `scaleY` \| `mask-bottom` \| `mask-top` \| `flash` \| `bounce` \| `swing` \| `swing-y` \| `swing-rotate`. |
36 | | mode | string | `smooth` | animate sport mode. `smooth` \| `reverse` \| `random` \| `sync` |
37 | | duration | number | `450` | Except for special animation `flash` \| `bounce` \| `swing` \| `swing-y` \| `swing-rotate`. one text animation duration |
38 | | delay | number | `0` | animation overall delay. |
39 | | interval | number \| func | `50` | animation interval, is function: `function: (e: { key: string }) => number.` Key is split text plus sequence(text-1). example: `text`, key is `t-0`、`e-1`、`x-2`、`t-3`. |
40 | | split | func | `null` | children split, return string |
41 |
42 | ### Inherit TweenOneGroup API
43 |
44 | [TweenOneGroup API](/api/tween-one#TweenOneGroup-API)
45 |
46 | | name | type | default | description |
47 | | ------------------ | --------------------- | ------------------------- | ---- |
48 | | appear | boolean | true | Whether the element has an initial appear animation. |
49 | | enter | object / array / func | { x: 30, opacity: 0, type: 'from' } | Enter the tween-one animation data, if the array is tween-one timeline. func reference queue-anim, callbac({key,index}) |
50 | | leave | object / array / func | { x: 30, opacity: 0 }| Leave the tween-one animation data, same as above. |
51 | | onEnd | func | - | Callback after each animation ends. |
52 | | animatingClassName | array | `['tween-one-entering', 'tween-one-leaving']` | The style of entering and leaving, if it is a component form, you need to bring the className to your component. |
53 | | resetStyle | boolean | true | TweenOne's `resetStyle`, resets the initial style when switching animations. |
54 | | exclusive | boolean | false | Whether to allow new animations to be executed immediately upon switching. `enter => leave`: execute leaving animation immediately. |
55 | | component | React.Element/String | div | - |
--------------------------------------------------------------------------------
/components/texty/index.zh-CN.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: 文字动画
5 | en-US: TextyAnim
6 | ---
7 |
8 | 一个针对文字标题的进行进出场动画的组件,提供非富的动画效果,也可以随自已的需求来配置完成不同的效果,具体参数请参见 [API](/api/texty);
9 |
10 | ## 何时使用
11 |
12 | - 在进出场的动画元素里,针对标题或正文文字进行间隔性动画时使用。
13 | - 每个词语的不同时间进场的动画。
14 |
15 | ---
16 | ## 怎么使用
17 |
18 | ### 安装
19 |
20 | ```bash
21 | $ npm install rc-texty --save
22 | ```
23 | ### 使用
24 |
25 | ```jsx
26 | import Texty from 'rc-texty';
27 | ReactDOM.render(text , mountNode);
28 | ```
29 |
30 |
31 | ## API
32 |
33 | | 参数 | 类型 | 默认 | 说明 |
34 | | --------- | -------------- | -------- | --------- |
35 | | className | string | `null` | 组件自定义样式. |
36 | | prefixCls | string | `texty` | 组件默认自带样式. |
37 | | type | string | `top` | 动画的样式, 提供: 'left' \| 'right' \| 'top' \| 'bottom' \|'alpha' \| 'scale' \| 'scaleX' \| 'scaleBig' \| 'scaleY' \| 'mask-bottom' \| 'mask-top' \| 'flash' \| 'bounce' \| 'swing' \| 'swing-y' \| 'swing-rotate'. |
38 | | mode | string | `smooth` | 动画的类型,如倒放,随机出现等。提供: 'smooth' \| 'reverse' \| 'random' \| 'sync' |
39 | | duration | number | `450` | 除 'flash' \| 'bounce' \| 'swing' \| 'swing-y' \| 'swing-rotate' 外的动画时间 |
40 | | delay | number | `0` | 动画开始前的延时. |
41 | | interval | number \| func | `50` | 每单个文字的间隔出现的时间, 如果是 `function: (e: { key: string }) => number.` Key 是 `split` 后的单个文字的加当前文字的序列,如 text, key 是 `t-0`、`e-1`、`x-2`、`t-3`. |
42 | | split | func | `null` | 自定义将文字拆分,需要返回个数组,默认将每个字符拆分。 |
43 |
44 | ### Inherit TweenOneGroup API
45 |
46 | [TweenOneGroup API](/api/tween-one#TweenOneGroup-API)
47 |
48 | | 参数 | 类型 | 默认 | 说明 |
49 | | ------------------ | --------------------- | ------------------- | ------------------------------ |
50 | | appear | boolean | true | 元素是否有刚开始的进场动画 |
51 | | enter | object / array / func | `null` | 进场的 tween-one 数据,如果是数组是 tween-one 的 timeline。 func 参照 queue-anim, callbac({ key, index }) |
52 | | leave | object / array / func | `null` | 出场时的数据,同上 |
53 | | onEnd | func | - | 每个动画结束后回调 |
54 | | animatingClassName | array | `['tween-one-entering', 'tween-one-leaving']` | 进出场的样式,如果是组件形式,需把 className 带到你的组件里 |
55 | | exclusive | boolean | false | 是否允许在切换时立即执行新的动画。 `enter => leave`:立即执行离开动画 |
56 | | component | React.Element/String | div | 需要替换的标签 |
--------------------------------------------------------------------------------
/components/tween-one/demo/bezier.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 8
3 | title:
4 | zh-CN: 曲线动画
5 | en-US: Curve Animate
6 | mouseEnter: true
7 | vertical: true
8 | ---
9 |
10 | ## zh-CN
11 | 贝赛尔曲线动画。 gsap 的 BezierPlugin 曲线动画;
12 |
13 | ## en-US
14 | Bezier curve animation. ref Gzap BezierPlugin curve animation;
15 |
16 | ```jsx
17 | import PropTypes from 'prop-types';
18 | import TweenOne from 'rc-tween-one';
19 | import BezierPlugin from 'rc-tween-one/lib/plugin/BezierPlugin';
20 | TweenOne.plugins.push(BezierPlugin);
21 | class Demo extends React.Component {
22 |
23 | constructor(props) {
24 | super();
25 | this.animation = {
26 | bezier: {
27 | type: 'soft',
28 | autoRotate: true,
29 | vars: [
30 | { x: 150, y: 150 },
31 | { x: 300, y: 0 },
32 | { x: 450, y: 150 },
33 | { x: 600, y: 0 },
34 | ],
35 | },
36 | repeat: -1,
37 | yoyo: true,
38 | duration: 5000,
39 | };
40 | }
41 |
42 | render() {
43 | return (
44 |
45 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | );
58 | }
59 | }
60 | Demo.propTypes = {
61 | children: PropTypes.any,
62 | className: PropTypes.string,
63 | paused: PropTypes.bool,
64 | };
65 | ReactDOM.render( , mountNode);
66 |
67 | ```
68 |
--------------------------------------------------------------------------------
/components/tween-one/demo/children.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 4
3 | title:
4 | zh-CN: 数值变化
5 | en-US: Number Change
6 | ---
7 |
8 | ## zh-CN
9 | 输入与当前不同的数值,再点开始,不输入将过渡到 10000。
10 |
11 | ## en-US
12 | Enter a different value from the current one, then click Start. No input will transition to 10000.
13 |
14 | ```jsx
15 | import PropTypes from 'prop-types';
16 | import { InputNumber, Button, Checkbox } from 'antd';
17 | import TweenOne from 'rc-tween-one';
18 | import Children from 'rc-tween-one/lib/plugin/ChildrenPlugin';
19 |
20 | TweenOne.plugins.push(Children);
21 |
22 | class Demo extends React.Component {
23 |
24 | constructor(props) {
25 | super(props);
26 | this.state = {
27 | value: 10000,
28 | animation: null,
29 | formatMoney: false,
30 | };
31 | }
32 |
33 | onChangeMoney = (e) => {
34 | this.setState({
35 | formatMoney: e.target.checked
36 | })
37 | }
38 |
39 | onClick = () => {
40 | const { value, formatMoney } = this.state;
41 | this.setState({
42 | animation: {
43 | Children: {
44 | value: typeof value === 'number' ? value : 10000,floatLength: 2,
45 | formatMoney,
46 | },
47 | duration: 1000,
48 | }
49 | })
50 | }
51 |
52 | onChange = (value) => {
53 | console.log(value)
54 | this.setState({
55 | value,
56 | });
57 | }
58 |
59 | render() {
60 | return (
61 |
70 |
71 |
75 | 0
76 |
77 |
81 | to money
82 |
87 | Start
88 |
89 |
90 |
91 | );
92 | }
93 | }
94 | Demo.propTypes = {
95 | children: PropTypes.any,
96 | className: PropTypes.string,
97 | paused: PropTypes.bool,
98 | };
99 | ReactDOM.render( , mountNode);
100 | ```
101 |
--------------------------------------------------------------------------------
/components/tween-one/demo/control.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | title:
4 | zh-CN: 变更动画参数
5 | en-US: Change Param
6 | mouseEnter: true
7 | ---
8 |
9 | ## zh-CN
10 | 可操作型变更动画。
11 |
12 | ## en-US
13 | Operational change animation.
14 |
15 | ```jsx
16 | import PropTypes from 'prop-types';
17 | import TweenOne from 'rc-tween-one';
18 | import Button from 'antd/lib/button';
19 |
20 | class Demo extends React.Component {
21 |
22 | constructor(props) {
23 | super(props);
24 | this.moment = null;
25 | this.animation = { left: '70%', duration: 2000 };
26 | this.state = {
27 | moment: null,
28 | paused: true,
29 | reverse: false,
30 | };
31 | }
32 |
33 | onPause = () => {
34 | this.setState({
35 | paused: true,
36 | moment: null,
37 | });
38 | }
39 |
40 | onReverse = () => {
41 | this.setState({
42 | paused: false,
43 | reverse: true,
44 | moment: null,
45 | });
46 | }
47 |
48 | onRestart = () => {
49 | this.setState({
50 | paused: false,
51 | reverse: false,
52 | moment: 0,
53 | }, () => {
54 | this.setState({
55 | moment: null,
56 | });
57 | });
58 | }
59 |
60 | onClick = () => {
61 | this.setState({
62 | paused: false,
63 | reverse: false,
64 | moment: null,
65 | });
66 | }
67 |
68 |
69 | render() {
70 | return (
71 |
72 |
80 |
89 | play
90 | pause
91 | reverse
92 | restart
93 |
94 |
95 | );
96 | }
97 | }
98 | Demo.propTypes = {
99 | children: PropTypes.any,
100 | className: PropTypes.string,
101 | paused: PropTypes.bool,
102 | };
103 | ReactDOM.render( , mountNode);
104 |
105 | ```
106 |
--------------------------------------------------------------------------------
/components/tween-one/demo/easingPath.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: 路径缓动
5 | en-US: Path Easing
6 |
7 | mouseEnter: true
8 | ---
9 | ## zh-CN
10 | 鼠标经过或手指按下可查看旋转效果。
11 |
12 | ## en-US
13 | Mouse hover or touch see the animation.
14 |
15 | ```jsx
16 | import PropTypes from 'prop-types';
17 | import TweenOne from 'rc-tween-one';
18 |
19 | const p0 = 'M0,100 L25,100 C34,20 40,0 100,0';
20 | const p1 = 'M0,100 C5,120 25,130 25,100 C30,60 40,75 58,90 C69,98.5 83,99.5 100,100';
21 | const ease0 = TweenOne.easing.path(p0);
22 | const ease1 = TweenOne.easing.path(p1);
23 | class Demo extends React.Component {
24 | constructor(props) {
25 | super(props);
26 | this.animation = [
27 | {
28 | repeatDelay: 500,
29 | y: -70,
30 | repeat: -1,
31 | yoyo: true,
32 | ease: ease0,
33 | duration: 1000
34 | },
35 | {
36 | repeatDelay: 500,
37 | appearTo: 0,
38 | scaleX: 0,
39 | scaleY: 2,
40 | repeat: -1,
41 | yoyo: true,
42 | ease: ease1,
43 | duration: 1000,
44 | }
45 | ];
46 | }
47 |
48 | render() {
49 | return (
50 |
51 |
60 |
61 | );
62 | }
63 | }
64 | Demo.propTypes = {
65 | children: PropTypes.any,
66 | className: PropTypes.string,
67 | paused: PropTypes.bool,
68 | };
69 | ReactDOM.render( , mountNode);
70 | ```
71 |
--------------------------------------------------------------------------------
/components/tween-one/demo/path.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 7
3 | title:
4 | zh-CN: 曲线路径动画
5 | en-US: Curve Path Animation
6 | mouseEnter: true
7 |
8 | ---
9 | ## zh-CN
10 | 曲线路径动画。
11 |
12 | ## en-US
13 | Mouse hover or touch see the animation. Curve Path Animation.
14 |
15 | ```jsx
16 | import PropTypes from 'prop-types';
17 | import TweenOne from 'rc-tween-one';
18 | import PathPlugin from 'rc-tween-one/lib/plugin/PathPlugin';
19 | TweenOne.plugins.push(PathPlugin);
20 |
21 | class Demo extends React.Component {
22 | constructor(props) {
23 | super(props);
24 | this.path = `M3.5,175V19c0,0,1-8.75,8.25-11.5S26.5,8,26.5,8l54,53.25
25 | c0,0,7,8.25,14.5,0.75s51.5-52.25,51.5-52.25s9.75-7,18-2s7.75,11.5,7.75,11.5
26 | v104c0,0-0.5,15.75-15.25,15.75s-15.75-15-15.75-15V68.5c0,0-0.125-9.125-6-3.25
27 | s-36.25,36-36.25,36s-11.625,11.875-24-0.5S40.25,65.5,40.25,65.5
28 | s-5.75-5.25-5.75,2s0,107.25,0,107.25s-0.75,13.5-14.5,13.5S3.5,175,3.5,175z`;
29 | this.animation = {
30 | path: this.path,
31 | repeat: -1,
32 | duration: 5000,
33 | ease: 'linear'
34 | };
35 | }
36 |
37 | render() {
38 | return (
39 |
50 | );
51 | }
52 | }
53 | Demo.propTypes = {
54 | children: PropTypes.any,
55 | className: PropTypes.string,
56 | paused: PropTypes.bool,
57 | };
58 | ReactDOM.render( , mountNode);
59 |
60 | ```
61 |
--------------------------------------------------------------------------------
/components/tween-one/demo/position.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: 基本动画效果
5 | en-US: Basic Animate
6 | mouseEnter: true
7 | ---
8 |
9 | ## zh-CN
10 | 鼠标经过或手指按下可查看位移效果。如 `x, y, z, scale, rotate, blur, marign`等, 更多参数参考 [动画术语](language/animate-term);
11 |
12 | ## en-US
13 | Mouse hover or touch see the animation. For: `x, y, z, scale, rotate, blur, marign` etc, more ref [Animate term](language/animate-term);
14 |
15 |
16 | ```jsx
17 | import TweenOne from 'rc-tween-one';
18 | import PropTypes from 'prop-types';
19 |
20 | function Demo(props) {
21 | return (
22 |
35 | );
36 | }
37 |
38 | Demo.propTypes = {
39 | children: PropTypes.any,
40 | className: PropTypes.string,
41 | paused: PropTypes.bool,
42 | };
43 |
44 | ReactDOM.render( , mountNode);
45 |
46 | ```
47 |
--------------------------------------------------------------------------------
/components/tween-one/demo/svgDraw.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 5
3 | title:
4 | zh-CN: SVG 线性动画
5 | en-US: SVG Linear Animate
6 | ---
7 |
8 | ## zh-CN
9 | 基本线性生成与消失的动态效果。
10 |
11 | ## en-US
12 | Basic linear generation and disappearing dynamic effects.
13 |
14 | ```jsx
15 | import TweenOne from 'rc-tween-one';
16 | import Button from 'antd/lib/button';
17 | import SvgDrawPlugin from 'rc-tween-one/lib/plugin/SvgDrawPlugin';
18 | import PropTypes from 'prop-types';
19 | TweenOne.plugins.push(SvgDrawPlugin);
20 |
21 | const dataStartArr = ['30 150', '50% 50%', '30% 200', '20 30%', 0, '100%'];
22 | let i = 0;
23 | class Demo extends React.Component {
24 |
25 | constructor(props) {
26 | super(props);
27 | this.state = {
28 | tweenData: '100%',
29 | };
30 | }
31 |
32 | onClick() {
33 | const tweenData = dataStartArr[i];
34 | this.setState({
35 | tweenData,
36 | });
37 | i++;
38 | i = i >= dataStartArr.length ? 0 : i;
39 | }
40 |
41 | render() {
42 | return (
43 |
44 |
45 | Switch
46 |
47 |
50 |
56 |
57 |
Current Param: {this.state.tweenData}
58 |
59 | );
60 | }
61 | }
62 | Demo.propTypes = {
63 | children: PropTypes.any,
64 | className: PropTypes.string,
65 | paused: PropTypes.bool,
66 | };
67 | ReactDOM.render( , mountNode);
68 |
69 | ```
70 |
--------------------------------------------------------------------------------
/components/tween-one/demo/svgMorph.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 6
3 | title:
4 | zh-CN: SVG 形变动画
5 | en-US: SVG Deformation Animate
6 | mouseEnter: true
7 | ---
8 |
9 | ## zh-CN
10 | SVG 图形形状变化的动态效果。
11 |
12 | ## en-US
13 | The dynamic effect of SVG graphic shape changes.
14 |
15 | ```jsx
16 | import TweenOne from 'rc-tween-one';
17 | import Button from 'antd/lib/button';
18 | import SvgMorphPlugin from 'rc-tween-one/lib/plugin/SvgMorphPlugin';
19 | import PropTypes from 'prop-types';
20 | TweenOne.plugins.push(SvgMorphPlugin);
21 |
22 | class Demo extends React.Component {
23 |
24 | constructor(props) {
25 | super(props);
26 | this.animation = {
27 | d: 'M60,10L60,90L140,90L140,10Z',
28 | yoyo: true,
29 | repeat: -1,
30 | duration: 1000,
31 | };
32 | this.state = {
33 | tweenData: '100%',
34 | };
35 | }
36 | render() {
37 | return (
38 |
39 |
42 |
50 |
51 |
52 | );
53 | }
54 | }
55 | Demo.propTypes = {
56 | children: PropTypes.any,
57 | className: PropTypes.string,
58 | paused: PropTypes.bool,
59 | };
60 | ReactDOM.render( , mountNode);
61 |
62 | ```
63 |
--------------------------------------------------------------------------------
/components/tween-one/demo/timeline.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 时间轴效果
5 | en-US: Timeline
6 | mouseEnter: true
7 | ---
8 | ## zh-CN
9 | 鼠标经过或手指按下可查看时间轴效果, 时间轴效果,无限循环时间轴效果。
10 |
11 | ## en-US
12 | Mouse hover or touch see the animation. Timeline effects, infinite loop timeline effects.
13 |
14 | ```jsx
15 | import TweenOne from 'rc-tween-one';
16 | import PropTypes from 'prop-types';
17 |
18 | class Demo extends React.Component {
19 |
20 | constructor(props) {
21 | super(props);
22 | this.moment = null;
23 | this.animation = [
24 | { left: '-40%' },
25 | { left: '40%' },
26 | { top: '60px' },
27 | { scale: 0.7 },
28 | { scale: 1 },
29 | { top: 0 },
30 | { left: '0%' },
31 | ];
32 | }
33 |
34 |
35 | render() {
36 | return (
37 |
45 | );
46 | }
47 | }
48 | Demo.propTypes = {
49 | children: PropTypes.any,
50 | className: PropTypes.string,
51 | paused: PropTypes.bool,
52 | };
53 | ReactDOM.render( , mountNode);
54 |
55 | ```
56 |
--------------------------------------------------------------------------------
/exhibition/demo/list-sort.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 列表交换位置
5 | en-US: List Sort
6 | content:
7 | zh-CN: 页面里的 List 拖动来重新排列顺序。
8 | en-US: Drag the List on the page to rearrange the order.
9 | image: https://zos.alipayobjects.com/rmsportal/BgYxbsXLrUfkkRT.png
10 | ---
11 | ## zh-CN
12 | ListSort 组件地址: [地址](https://github.com/ant-design/ant-motion/blob/master/site/theme/template/other/ListSort.jsx)
13 |
14 | ## en-US
15 |
16 | ListSort: [Component URL](https://github.com/ant-design/ant-motion/blob/master/site/theme/template/other/ListSort.jsx)
17 |
18 | ```jsx
19 | import Icon from 'antd/lib/icon';
20 | import PropTypes from 'prop-types';
21 | import ListSort from '../../site/theme/template/other/ListSort';
22 |
23 | const dataArray = [
24 | {
25 | icon: 'question-circle-o',
26 | color: '#FF5500',
27 | title: 'Senior Product Designer',
28 | text: 'Senior Product Designer',
29 | },
30 | {
31 | icon: 'plus-circle-o',
32 | color: '#5FC296',
33 | title: 'Senior Animator',
34 | text: 'Senior Animator',
35 | },
36 | {
37 | icon: 'check-circle-o',
38 | color: '#2DB7F5',
39 | title: 'Visual Designer',
40 | text: 'Visual Designer',
41 | },
42 | {
43 | icon: 'cross-circle-o',
44 | color: '#FFAA00',
45 | title: 'Computer Engineer',
46 | text: 'Computer Engineer',
47 | },
48 | ];
49 | class ListSortDemo extends React.Component {
50 | static propTypes = {
51 | className: PropTypes.string,
52 | };
53 |
54 | static defaultProps = {
55 | className: 'list-sort-demo',
56 | };
57 |
58 | render() {
59 | const childrenToRender = dataArray.map((item, i) => {
60 | const {
61 | icon, color, title, text,
62 | } = item;
63 | return (
64 |
65 |
66 |
67 |
68 |
69 |
{title}
70 |
{text}
71 |
72 |
73 | );
74 | });
75 | return (
76 |
77 |
78 |
82 | {childrenToRender}
83 |
84 |
85 |
86 | );
87 | }
88 | }
89 |
90 | ReactDOM.render(
91 |
92 | , mountNode);
93 | ```
94 |
95 | ```css
96 | .list-sort-demo-wrapper {
97 | position: relative;
98 | background: #e6e6e6;
99 | overflow: hidden;
100 | height: 385px;
101 | }
102 |
103 | .list-sort-demo {
104 | margin: 40px auto;
105 | max-width: 350px;
106 | width: 90%;
107 | cursor: url('http://gtms02.alicdn.com/tps/i2/T1_PMSFLBaXXcu5FDa-20-20.png') 10 10,pointer!important;
108 | position: relative;
109 | height: 305px;
110 | }
111 | .list-sort-demo > div{
112 | overflow: hidden;
113 | }
114 |
115 | .list-sort-demo-list {
116 | background: #fff;
117 | border-radius: 6px;
118 | margin: 5px auto;
119 | padding: 10px;
120 | height: 70px;
121 | transition: box-shadow .5s, transform .5s;
122 | }
123 |
124 | .list-sort-demo-list.list-drag-selected{
125 | box-shadow: 0 8px 20px #E6E6E6;
126 | transform: scale(1.1) !important;
127 | }
128 |
129 | .list-sort-demo-icon {
130 | width: 20%;
131 | display: inline-block;
132 | text-align: center;
133 | font-size: 24px;
134 | line-height: 50px;
135 | vertical-align: top;
136 | }
137 | .list-sort-demo-text{
138 | width: 80%;
139 | display: inline-block;
140 | }
141 |
142 | .list-sort-demo-text h1 {
143 | font-size: 18px;
144 | }
145 |
146 | .list-sort-demo-text p{
147 | font-size: 12px;
148 | }
149 |
150 | @media screen and (max-width: 320px) {
151 | .list-sort-demo-text h1 {
152 | font-size: 14px;
153 | line-height: 28px;
154 | }
155 | }
156 | ```
157 |
--------------------------------------------------------------------------------
/exhibition/js/carousel3d.css:
--------------------------------------------------------------------------------
1 | .carousel-demo-wrapper {
2 | position: relative;
3 | background: #3949C0;
4 | background: linear-gradient(45deg, #1e5799 0%,#3949c0 0%,#4e7de4 100%);
5 | overflow: hidden;
6 | height: 500px;
7 | }
8 |
9 | .carousel-demo {
10 | width: 100%;
11 | height: 100%;
12 | }
13 |
14 | .carousel-wrapper {
15 | position: absolute;
16 | width: 250px;
17 | height: 300px;
18 | margin: auto;
19 | left: 0;
20 | right: 0;
21 | top: 120px;
22 | padding-top: 350px;
23 | margin-top: -350px;
24 | }
25 |
26 | .carousel {
27 | position: relative;
28 | width: 100%;
29 | margin: auto;
30 | height: 100%;
31 | }
32 |
33 | .carouselContent {
34 | transform-style: preserve-3d;
35 | width: 100%;
36 | }
37 |
38 | .itemWrapper {
39 | position: absolute;
40 | top: 0;
41 | left: 0;
42 | transform-style: preserve-3d;
43 | width: 100%;
44 | }
45 |
46 | .itemWrapper .rotateLayer .bgAndBlurLayer {
47 | border-radius: 8px;
48 | overflow: hidden;
49 | background: #fff;
50 | transition: filter .45s;
51 | margin: auto;
52 | }
53 |
54 | .itemWrapper .rotateLayer .bgAndBlurLayer .contentLayer {
55 | transition: opacity .65s;
56 | }
57 |
58 | .img-wrapper {
59 | height: 300px;
60 | background-size: cover;
61 | background-position: center;
62 | }
--------------------------------------------------------------------------------
/exhibition/js/detail-swich.css:
--------------------------------------------------------------------------------
1 | .details-switch-demo-wrapper {
2 | position: relative;
3 | overflow: hidden;
4 | height: 450px;
5 | transition: background 1s;
6 | }
7 |
8 | .details-switch-demo {
9 | margin: 40px auto;
10 | width: 600px;
11 | height: 370px;
12 | background: #fff;
13 | border-radius: 6px;
14 | overflow: hidden;
15 | position: relative;
16 | }
17 |
18 | .details-switch-demo-img-wrapper,
19 | .details-switch-demo-text-wrapper {
20 | width: 50%;
21 | display: inline-block;
22 | height: 100%;
23 | }
24 |
25 | .details-switch-demo-pic,
26 | .details-switch-demo-map {
27 | position: absolute;
28 | }
29 |
30 | .details-switch-demo-pic {
31 | width: 220px;
32 | top: 100px;
33 | left: 40px;
34 | }
35 |
36 | .details-switch-demo-map {
37 | width: 250px;
38 | top: 60px;
39 | left: 30px;
40 | }
41 | .details-switch-demo-map.map2{
42 | width: 200px;
43 | left: 50px;
44 | }
45 |
46 | .details-switch-demo-text-wrapper .banner-anim-elem {
47 | padding: 40px;
48 | }
49 |
50 | .details-switch-demo-text-wrapper h1 {
51 | font-size: 18px;
52 | margin: 5px auto;
53 | }
54 |
55 | .details-switch-demo-text-wrapper em {
56 | height: 2px;
57 | width: 60px;
58 | border-radius: 2px;
59 | display: block;
60 | }
61 |
62 | .details-switch-demo-text-wrapper p {
63 | font-size: 12px;
64 | margin-top: 10px;
65 | }
66 |
67 | .details-switch-demo-wrapper .anticon{
68 | position: absolute;
69 | font-size: 24px;
70 | top: 50%;
71 | margin-top: -12px;
72 | cursor: pointer;
73 | }
74 |
75 | .details-switch-demo-wrapper .anticon-left{
76 | left: 5px;
77 | z-index: 999;
78 | }
79 |
80 | .details-switch-demo-wrapper .anticon-right{
81 | right: 5px;
82 | }
83 | @media screen and (max-width: 414px) {
84 | .details-switch-demo {
85 | transform: scale(.6) translateX(12px);
86 | transform-origin: left center;
87 | }
88 | }
89 | @media screen and (max-width: 375px) {
90 | .details-switch-demo {
91 | transform: scale(.55) translateX(7px);
92 | }
93 | }
94 | @media screen and (max-width: 320px) {
95 | .details-switch-demo {
96 | transform: scale(.46) translateX(12px);
97 | }
98 | }
--------------------------------------------------------------------------------
/exhibition/js/linked-animate.css:
--------------------------------------------------------------------------------
1 | .linked-animate-demo-wrapper {
2 | overflow: hidden;
3 | height: 500px;
4 | background: #019BF0;
5 | position: relative;
6 | }
7 |
8 | .linked-animate-demo-box {
9 | position: absolute;
10 | width: 1280px;
11 | height: 600px;
12 | display: block;
13 | left: -100%;
14 | top: 0;
15 | bottom: 0;
16 | right: -100%;
17 | margin: auto;
18 | }
19 |
20 | .linked-animate-demo-block {
21 | position: absolute;
22 | transition: transform .45s ease;
23 | }
24 |
25 | .linked-animate-demo-block-child {
26 | border-radius: 100%;
27 | width: 100%;
28 | height: 100%;
29 | }
--------------------------------------------------------------------------------
/exhibition/js/list-anim-animateDemo.css:
--------------------------------------------------------------------------------
1 | .queue-demo-wrapper {
2 | position: relative;
3 | background: #CCE9F9;
4 | overflow: hidden;
5 | height: 340px;
6 |
7 | }
8 |
9 | .queue-demo {
10 | max-width: 300px;
11 | width: 90%;
12 | height: 340px;
13 | margin: auto;
14 | background: #fff;
15 | box-shadow: 0 5px 20px rgba(83, 145, 202, 0.8);
16 | cursor: url('http://gtms02.alicdn.com/tps/i2/T1_PMSFLBaXXcu5FDa-20-20.png') 10 10,pointer!important;
17 | }
18 |
19 | .queue-demo-header {
20 | height: 60px;
21 | border-top: 10px solid #265783;
22 | background: #29659B;
23 | line-height: 50px;
24 | color: #fff;
25 | }
26 |
27 | .queue-demo-header i {
28 | width: 15px;
29 | height: 2px;
30 | background: #fff;
31 | display: inline-block;
32 | position: relative;
33 | vertical-align: middle;
34 | margin-left: 10px;
35 | top: -2px;
36 | }
37 |
38 | .queue-demo-header i:before, .queue-demo-header i:after {
39 | display: block;
40 | content: '';
41 | background: #fff;
42 | width: 15px;
43 | height: 2px;
44 | position: absolute;
45 | }
46 |
47 | .queue-demo-header i:before {
48 | top: -4px;
49 | }
50 |
51 | .queue-demo-header i:after {
52 | top: 4px;
53 | }
54 |
55 | .queue-demo-header span {
56 | margin-left: 20px;
57 | font-size: 14px;
58 | }
59 |
60 | .queue-demo ul {
61 | overflow: hidden;
62 | }
63 |
64 | .queue-demo ul li {
65 | list-style: none;
66 | overflow: hidden;
67 | height: 70px;
68 | line-height: 70px;
69 | border-bottom: 1px solid #efefef;
70 | /*cursor: move;
71 | cursor: grab;
72 | cursor: -webkit-grab;*/
73 | user-select: none;
74 | -webkit-user-select: none;
75 | -moz-user-select: none;
76 | position: relative;
77 | }
78 |
79 | .queue-demo-img, .queue-demo ul li p {
80 | display: inline-block;
81 | }
82 |
83 | .queue-demo ul li.queue-anim-leaving {
84 | position: relative !important;
85 | }
86 |
87 | .queue-demo-img {
88 | margin: 0 20px;
89 | }
90 |
91 | .queue-demo-delete {
92 | width: 60px;
93 | background: #FF4058;
94 | text-align: center;
95 | font-size: 16px;
96 | height: 67px;
97 | position: absolute;
98 | right: 0;
99 | top: 1px;
100 | }
101 |
102 | .queue-demo-delete a {
103 | color: #fff;
104 | width: 100%;
105 | height: 100%;
106 | display: block;
107 | }
108 |
109 | .queue-demo-content {
110 | background: #fff;
111 | position: relative;
112 | }
113 |
114 | /* animate 样式*/
115 | .list-slide-enter, .list-slide-close-enter,.list-slide-close-leave {
116 | animation-duration: .3s;
117 | animation-fill-mode: both;
118 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
119 | animation-play-state: paused
120 | }
121 |
122 | .list-slide-leave {
123 | animation-duration: .3s;
124 | animation-fill-mode: both;
125 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
126 | animation-play-state: paused;
127 | }
128 |
129 | .list-slide-enter.list-slide-enter-active {
130 | animation-name: slideOpen;
131 | animation-play-state: running;
132 | }
133 |
134 | .list-slide-leave.list-slide-leave-active,
135 | .list-slide-close-enter.list-slide-close-enter-active,
136 | .list-slide-close-leave.list-slide-close-leave-active
137 | {
138 | animation-name: slideClose;
139 | animation-play-state: running;
140 | }
141 |
142 | @keyframes slideOpen {
143 | to {
144 | transform: translateX(-60px);
145 | }
146 | }
147 |
148 | @keyframes slideClose {
149 | to {
150 | transform: translateX(0px);
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/exhibition/js/list-anim-tweeOneDemo.css:
--------------------------------------------------------------------------------
1 | .queue-demo-wrapper {
2 | position: relative;
3 | background: #CCE9F9;
4 | overflow: hidden;
5 | height: 340px;
6 | }
7 |
8 | .queue-demo {
9 | max-width: 300px;
10 | width: 90%;
11 | height: 340px;
12 | margin: auto;
13 | background: #fff;
14 | box-shadow: 0 5px 20px rgba(83, 145, 202, 0.8);
15 | cursor: url('http://gtms02.alicdn.com/tps/i2/T1_PMSFLBaXXcu5FDa-20-20.png') 10 10,pointer!important;
16 | }
17 |
18 | .queue-demo-header {
19 | height: 60px;
20 | border-top: 10px solid #265783;
21 | background: #29659B;
22 | line-height: 50px;
23 | color: #fff;
24 | }
25 |
26 | .queue-demo-header i {
27 | width: 15px;
28 | height: 2px;
29 | background: #fff;
30 | display: inline-block;
31 | position: relative;
32 | vertical-align: middle;
33 | margin-left: 10px;
34 | top: -2px;
35 | }
36 |
37 | .queue-demo-header i:before, .queue-demo-header i:after {
38 | display: block;
39 | content: '';
40 | background: #fff;
41 | width: 15px;
42 | height: 2px;
43 | position: absolute;
44 | }
45 |
46 | .queue-demo-header i:before {
47 | top: -4px;
48 | }
49 |
50 | .queue-demo-header i:after {
51 | top: 4px;
52 | }
53 |
54 | .queue-demo-header span {
55 | margin-left: 20px;
56 | font-size: 14px;
57 | }
58 |
59 | .queue-demo ul {
60 | overflow: hidden;
61 | }
62 |
63 | .queue-demo ul li {
64 | list-style: none;
65 | overflow: hidden;
66 | height: 70px;
67 | line-height: 70px;
68 | border-bottom: 1px solid #efefef;
69 | /* cursor: move;
70 | cursor: grab;
71 | cursor: -webkit-grab;*/
72 | user-select: none;
73 | -webkit-user-select: none;
74 | -moz-user-select: none;
75 | position: relative;
76 | }
77 |
78 | .queue-demo-img, .queue-demo ul li p {
79 | display: inline-block;
80 | }
81 | .queue-demo ul li.queue-anim-leaving{
82 | position: relative !important;
83 | }
84 | .queue-demo-img {
85 | margin: 0 20px;
86 | }
87 |
88 | .queue-demo-delete {
89 | width: 60px;
90 | background: #FF4058;
91 | text-align: center;
92 | font-size: 16px;
93 | height: 67px;
94 | position: absolute;
95 | right: 0;
96 | top: 1px;
97 | }
98 |
99 | .queue-demo-delete a {
100 | color: #fff;
101 | width: 100%;
102 | height: 100%;
103 | display: block;
104 | }
105 |
106 | .queue-demo-content {
107 | background: #fff;
108 | position: relative;
109 | }
110 |
--------------------------------------------------------------------------------
/exhibition/js/list-sort.css:
--------------------------------------------------------------------------------
1 | .list-sort-demo-wrapper {
2 | position: relative;
3 | background: #E15FFF;
4 | overflow: hidden;
5 | height: 385px;
6 | }
7 |
8 | .list-sort-demo {
9 | margin: 40px auto;
10 | max-width: 350px;
11 | width: 90%;
12 | cursor: url('http://gtms02.alicdn.com/tps/i2/T1_PMSFLBaXXcu5FDa-20-20.png') 10 10,pointer!important;
13 | position: relative;
14 | height: 305px;
15 | }
16 | .list-sort-demo > div{
17 | overflow: hidden;
18 | }
19 |
20 | .list-sort-demo-list {
21 | background: #fff;
22 | border-radius: 6px;
23 | margin: 5px auto;
24 | padding: 10px;
25 | height: 70px;
26 | transition: box-shadow .5s, transform .5s;
27 | }
28 |
29 | .list-sort-demo-list.list-drag-selected{
30 | box-shadow: 0 8px 20px #AF288E;
31 | transform: scale(1.1) !important;
32 | }
33 |
34 | .list-sort-demo-icon {
35 | width: 20%;
36 | display: inline-block;
37 | text-align: center;
38 | font-size: 24px;
39 | line-height: 50px;
40 | vertical-align: top;
41 | }
42 | .list-sort-demo-text{
43 | width: 80%;
44 | display: inline-block;
45 | }
46 |
47 | .list-sort-demo-text h1 {
48 | font-size: 18px;
49 | }
50 |
51 | .list-sort-demo-text p{
52 | font-size: 12px;
53 | }
54 |
55 | @media screen and (max-width: 320px) {
56 | .list-sort-demo-text h1 {
57 | font-size: 14px;
58 | line-height: 28px;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/exhibition/js/list-sort.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Icon from 'antd/lib/icon';
3 | import PropTypes from 'prop-types';
4 | import ListSort from '../../src/edit/template/components/ListSort';
5 | import './list-sort.css';
6 |
7 | const dataArray = [
8 | {
9 | icon: 'question-circle-o',
10 | color: '#FF5500',
11 | title: 'Senior Product Designer',
12 | text: 'Senior Product Designer',
13 | },
14 | {
15 | icon: 'plus-circle-o',
16 | color: '#5FC296',
17 | title: 'Senior Animator',
18 | text: 'Senior Animator',
19 | },
20 | {
21 | icon: 'check-circle-o',
22 | color: '#2DB7F5',
23 | title: 'Visual Designer',
24 | text: 'Visual Designer',
25 | },
26 | {
27 | icon: 'cross-circle-o',
28 | color: '#FFAA00',
29 | title: 'Computer Engineer',
30 | text: 'Computer Engineer',
31 | },
32 | ];
33 | export default class ListSortDemo extends React.Component {
34 | static propTypes = {
35 | className: PropTypes.string,
36 | };
37 |
38 | static defaultProps = {
39 | className: 'list-sort-demo',
40 | };
41 |
42 | render() {
43 | const childrenToRender = dataArray.map((item, i) => {
44 | const {
45 | icon, color, title, text,
46 | } = item;
47 | return (
48 |
49 |
50 |
51 |
52 |
53 |
{title}
54 |
{text}
55 |
56 |
57 | );
58 | });
59 | return (
60 |
61 |
62 |
66 | {childrenToRender}
67 |
68 |
69 |
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/exhibition/js/logo-gather-anim.css:
--------------------------------------------------------------------------------
1 | .logo-gather-demo-edit-wrapper {
2 | position: absolute;
3 | bottom: 0;
4 | width: 100%;
5 | background: #f1f1f1;
6 | padding: 0 5%;
7 | line-height: 45px;
8 | }
9 |
10 | .logo-gather-demo-edit-wrapper ul {
11 | display: block;
12 | width: 100%;
13 | overflow: hidden;
14 | }
15 |
16 | .logo-gather-demo-edit-wrapper ul li:first-child {
17 | margin-left: 0;
18 | }
19 |
20 | .logo-gather-demo-edit-wrapper ul li {
21 | float: left;
22 | vertical-align: middle;
23 | margin: 0 5px;
24 | }
25 |
26 | .logo-gather-demo-wrapper {
27 | position: relative;
28 | background: #019BF0;
29 | overflow: hidden;
30 | height: 500px;
31 | }
32 |
33 | .logo-gather-demo-wrapper .point-wrapper {
34 | position: absolute;
35 | }
36 |
37 | .logo-gather-demo-wrapper .point {
38 | border-radius: 100%;
39 | }
40 |
41 | .logo-gather-demo-wrapper .right-side {
42 | width: 300px;
43 | height: 360px;
44 | position: absolute;
45 | right: 0;
46 | top: 0;
47 | bottom: 0;
48 | left: 0;
49 | margin: auto;
50 | }
51 |
52 | .logo-gather-demo-wrapper .right-side * {
53 | pointer-events: none;
54 | }
55 |
56 | @media screen and (max-width: 414px) {
57 | .exhibition-details-demo {
58 | overflow: hidden;
59 | }
60 |
61 | .logo-gather-demo-edit-wrapper {
62 | transform: translateY(100%);
63 | transition: transform .45s ease-in-out;
64 | }
65 |
66 | .logo-gather-demo-edit-wrapper.open{
67 | transform: translateY(0);
68 | }
69 |
70 | .logo-gather-demo-edit-wrapper .anticon-down{
71 | transition: transform .45s ease-in-out;
72 | }
73 |
74 | .logo-gather-demo-edit-wrapper.open .anticon-down{
75 | transform: rotate(180deg);
76 | }
77 |
78 | .logo-gather-demo-edit-wrapper > div {
79 | width: 90%;
80 | line-height: 24px !important;
81 | margin-bottom: 5px;
82 | }
83 |
84 | .exhibition-details-demo .edit-button{
85 | position: absolute;
86 | top: -20px;
87 | width: 30px;
88 | height: 20px;
89 | border-radius: 30px 30px 0 0;
90 | background: #f1f1f1;
91 | text-align: center;
92 | left: 0;
93 | right: 0;
94 | margin: auto;
95 | box-shadow: 0 -5px 5px rgba(0, 0, 0, 0.15);
96 | }
97 |
98 | .logo-gather-demo-edit-wrapper ul {
99 | margin: 5px auto;
100 | }
101 |
102 | .phone-float-none {
103 | clear: both;
104 | margin-left: 0 !important;
105 | }
106 |
107 | .none {
108 | display: none;
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/exhibition/js/money.less:
--------------------------------------------------------------------------------
1 | .addMoneyAnim {
2 | background: url('https://gw.alipayobjects.com/zos/rmsportal/fseEOKMDOXOieJiHKuQg.png') no-repeat;
3 | background-size: 420px 104px;
4 | width: 52px;
5 | height: 52px;
6 | animation: rotateMoney 0.45s step-start infinite;
7 | }
8 |
9 | .addMoneyFrame(@one, @frame, @i: 0, @name: 0%) when (@i =< @frame) {
10 | .addMoneyFrame(@one, @frame, @i + 1, (100% / @frame * (@i + 1)));
11 | @{name} {
12 | background-position: -(mod(@i, @one) * 52px) -(floor(@i / @one)*52px);
13 | }
14 | }
15 |
16 | @keyframes rotateMoney {
17 | .addMoneyFrame(8, 15);
18 | }
--------------------------------------------------------------------------------
/exhibition/js/pic-details-anim.css:
--------------------------------------------------------------------------------
1 | /* 外壳样式 */
2 | .pic-details-demo-wrapper {
3 | position: relative;
4 | background: #DEEDCC;
5 | overflow: hidden;
6 | height: 500px;
7 | }
8 |
9 | .pic-details-demo {
10 | margin: 40px auto;
11 | box-shadow: 0 10px 40px #C7D7B5;
12 | width: 60%;
13 | min-width: 550px;
14 | height: 420px;
15 | background: #fff;
16 | border-radius: 6px;
17 | overflow: hidden;
18 | }
19 |
20 | .pic-details-demo-header {
21 | height: 32px;
22 | line-height: 32px;
23 | background: #000;
24 | }
25 |
26 | .pic-details-demo-header ul li {
27 | list-style: none;
28 | width: 8px;
29 | height: 8px;
30 | display: inline-block;
31 | border-radius: 4px;
32 | margin: 0 5px 0 0;
33 | }
34 |
35 | .pic-details-demo-header ul li:nth-child(1) {
36 | background: #CF3333;
37 | margin-left: 3%;
38 | }
39 |
40 | .pic-details-demo-header ul li:nth-child(2) {
41 | background: #DEC811;
42 | }
43 |
44 | .pic-details-demo-header ul li:nth-child(3) {
45 | background: #28C026;
46 | }
47 |
48 | .pic-details-demo-header ul li:nth-child(4) {
49 | background: #fff;
50 | width: 80%;
51 | height: 16px;
52 | vertical-align: middle;
53 | margin: 0 10px;
54 | }
55 |
56 | .pic-details-demo-header ul li:nth-child(5),
57 | .pic-details-demo-header ul li:nth-child(5):before,
58 | .pic-details-demo-header ul li:nth-child(5):after {
59 | width: 20px;
60 | height: 2px;
61 | background: #BABABA;
62 | border-radius: 2px;
63 | }
64 |
65 | .pic-details-demo-header ul li:nth-child(5) {
66 | vertical-align: middle;
67 | margin-left: 5px;
68 | position: relative;
69 | }
70 |
71 | .pic-details-demo-header ul li:nth-child(5):before,
72 | .pic-details-demo-header ul li:nth-child(5):after {
73 | content: '';
74 | display: block;
75 | position: absolute;
76 | }
77 |
78 | .pic-details-demo-header ul li:nth-child(5):before {
79 | top: -6px;
80 | }
81 |
82 | .pic-details-demo-header ul li:nth-child(5):after {
83 | top: 6px;
84 | }
85 |
86 | /* 外壳 end */
87 | /* 标题 */
88 | .pic-details-demo-title {
89 | width: 95%;
90 | margin: 20px auto;
91 | text-align: center;
92 | }
93 |
94 | .pic-details-demo-title h1 {
95 | color: #666666;
96 | font-size: 26px;
97 | }
98 |
99 | .pic-details-demo-title p {
100 | color: #878787;
101 | font-size: 12px;
102 | }
103 |
104 | /* 图片 */
105 | .pic-details-demo-image-wrapper {
106 | position: relative;
107 | list-style: none;
108 | width: 500px;
109 | height: 290px;
110 | margin: auto;
111 | }
112 |
113 | .pic-details-demo-image-wrapper li {
114 | width: 110px;
115 | height: 76px;
116 | position: absolute;
117 | }
118 |
119 | .pic-details-demo-image-box-shadow {
120 | box-shadow: 0 0 0 rgba(140, 140, 140, 0);
121 | height: 100%;
122 | transition: box-shadow .3s;
123 | }
124 |
125 | .pic-details-demo-image-wrapper li.open .pic-details-demo-image-box-shadow {
126 | box-shadow: 0 2px 8px rgba(140, 140, 140, 50);
127 | }
128 |
129 | .pic-details-demo-image-wrapper li a {
130 | width: 110px;
131 | z-index: 1;
132 | display: inline-block;
133 | position: absolute;
134 | }
135 |
136 | .pic-details-demo-image-wrapper li a, .pic-details-demo-image-wrapper li a img {
137 | display: block;
138 | }
139 |
140 | .pic-details-demo-text-wrapper {
141 | width: 50%;
142 | background: #fff;
143 | padding: 10px 15px;
144 | height: 175px;
145 | vertical-align: top;
146 | display: inline-block;
147 | position: absolute;
148 | }
149 |
150 | .pic-details-demo-text-wrapper h1 {
151 | font-size: 18px;
152 | margin: 5px auto;
153 | }
154 |
155 | .pic-details-demo-text-wrapper i {
156 | position: absolute;
157 | top: 10px;
158 | right: 10px;
159 | cursor: pointer;
160 | }
161 |
162 | .pic-details-demo-text-wrapper em {
163 | height: 2px;
164 | width: 60px;
165 | background: #FA1F4E;
166 | border-radius: 2px;
167 | display: block;
168 | }
169 |
170 | .pic-details-demo-text-wrapper p {
171 | font-size: 12px;
172 | margin-top: 10px;
173 | line-height: 16px;
174 | }
175 | @media screen and (max-width: 414px) {
176 | .pic-details-demo{
177 | transform: scale(.65) translateX(12px);
178 | transform-origin: left center;
179 | }
180 | }
181 |
182 | @media screen and (max-width: 375px) {
183 | .pic-details-demo{
184 | transform: scale(.6) translateX(7px);
185 | }
186 | }
187 |
188 | @media screen and (max-width: 320px) {
189 | .pic-details-demo{
190 | transform: scale(.5) translateX(12px);
191 | }
192 | }
--------------------------------------------------------------------------------
/exhibition/js/snow.css:
--------------------------------------------------------------------------------
1 | .snow-demo-wrapper {
2 | background: #4777E3;
3 | overflow: hidden;
4 | height: 500px;
5 | display: flex;
6 | align-items: center;
7 | position: relative;
8 | }
9 |
10 | .snow-demo {
11 | width: 300px;
12 | height: 90%;
13 | margin: auto;
14 | position: relative;
15 | background-image: url(https://gw.alipayobjects.com/zos/rmsportal/dNpuKMDHFEpMGrTxdLVR.jpg);
16 | background-position: top;
17 | background-size: 100% auto;
18 | box-shadow: 0 0 32px rgba(0, 0, 0, 0.15);
19 | }
20 |
21 | .snow {
22 | width: 100%;
23 | height: 100%;
24 | position: absolute;
25 | top: 0;
26 | overflow: hidden;
27 | }
28 |
29 | .snowChild {
30 | position: absolute;
31 | top: 0;
32 | left: 0;
33 | }
34 |
35 | .snowRotate {
36 | transform-origin: center center;
37 | }
--------------------------------------------------------------------------------
/language/animate-term.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 6
3 | title:
4 | zh-CN: 动画术语
5 | en-US: animate term
6 | category:
7 | zh-CN: 动效参数
8 | en-US: TweenOne param
9 | ---
10 |
11 | ## 动画基本参数术语说明
12 |
13 | 以下描述以 tween-one 里的可支持 style 动画参数来说明动画基本术语。
14 |
15 | 动画默认参数: duration: 450毫秒, ease: 'easeInOutQuad'; 以下文本中出现的`到`为默认动画。
16 |
17 | ## 基本 style 可动画参数
18 |
19 | | 参数名称 | 说明 |
20 | |-------------------|---------------------|
21 | | width | `{ width: 100 }` 元素当前宽度到 100px |
22 | | maxWidth | `{ maxWidth: 100 }` 元素当前最大宽度到 100px |
23 | | minWidth | `{ minWidth: 100 }` 元素当前最小宽度到 100px |
24 | | height | `{ height: 100 }` 元素当前高度到 100px |
25 | | maxHeight | `{ maxHeight: 100 }` 元素当前最大高度到 100px |
26 | | minHeight | `{ minHeight: 100 }` 元素当前最小高度到 100px |
27 | | lineHeight | `{ lineHeight: 100 }` 区块行高到 100px |
28 | | opacity | `{ opacity: 0 }` 元素当前透明度到 0 |
29 | | top | `{ top: 100 }` 元素当前顶部距离到 100px, 需配合 `position: relative | absolute` |
30 | | right | `{ right: 100 }` 元素当前右部距离到 100px, 需配合 `position: relative | absolute` |
31 | | bottom | `{ bottom: 100 }` 元素当前下部距离到 100px, 需配合 `position: relative | absolute` |
32 | | left | `{ left: 100 }` 元素当前左部距离到 100px, 需配合 `position: relative | absolute` |
33 | | marginTop | `{ marginTop: 100 }` 元素当前顶部外边距离到 100px |
34 | | marginRight | `{ marginRight: 100 }` 元素当前右部外边距离到 100px |
35 | | marginBottom | `{ marginBottom: 100 }` 元素当前下部外边距离到 100px |
36 | | marginLeft | `{ marginLeft: 100 }` 元素当前左部外边距离到 100px |
37 | | paddingTop | `{ paddingTop: 100 }` 元素当前顶部内边距离到 100px |
38 | | paddingRight | `{ paddingRight: 100 }` 元素当前右部内边距离到 100px |
39 | | paddingBottom | `{ paddingBottom: 100 }` 元素当前下部内边距离到 100px |
40 | | paddingLeft | `{ paddingLeft: 100 }` 元素当前左部内边距离到 100px |
41 | | color | `{ color: '#FFFFFF' }` 元素当前文字颜色到白色 |
42 | | backgroundColor | `{ backgroundColor: '#FFFFFF' }` 元素当前背景颜色到白色 |
43 | | borderWidth | `{ borderWidth: 2 }` 元素当前边框宽度到 2px,同样可用 `borderTopWidth` `borderRightWidth` `borderBottomWidth` `borderLeftWidth` |
44 | | borderRadius | `{ borderRadius: 5 }` 元素当前圆角到 5px, 同上, 同样可用 `上 左 下 右` |
45 | | borderColor | `{ borderColor: '#FFFFFF' }` 元素当前边框颜色到白色 |
46 | | boxShadow | `{ boxShadow: '0 0 10px #000' }` 元素当前阴影模糊到 10px |
47 | | textShadow | `{ textShadow: '0 0 10px #000' }` 元素当前文字内容阴影模糊到 10px |
48 |
49 | ## transform 参数
50 |
51 | | 参数名称 | 说明 |
52 | |-------------------|---------------------|
53 | | translateX / x | `{ translateX: 10 } or { x: 10 } => transform: translateX(10px)`, x 方向的位置移动 10px |
54 | | translateY / y | `{ translateY: 10 } or { y: 10 } => transform: translateY(10px)`, y 方向的位置移动 10px |
55 | | translateZ / z | `{ translateZ: 10 } or { z: 10 } => transform: translateZ(10px)`, z 方向的位置移动 10px |
56 | | rotate | `{ rotate: 10 } => transform: rotate(10deg)` 元素以 transformOrigin 的中心点旋转 10deg |
57 | | rotateX | `{ rotateX: 10 } => transform: rotateX(10deg)` 元素以 transformOrigin 的中心点向 X 旋转 10deg |
58 | | rotateY | `{ rotateY: 10 } => transform: rotateY(10deg)` 元素以 transformOrigin 的中心点向 Y 旋转 10deg |
59 | | scale | `{ scale: 0 } => transform: scale(0)` 元素以 transformOrigin 的中心点缩放到 0, 不改变元素的宽高 |
60 | | scaleX | `{ scaleX: 0 } => transform: scaleX(0)` 元素以 transformOrigin 的中心点 X 缩放到 0, 不改变元素的宽高 |
61 | | scaleY | `{ scaleY: 0 } => transform: scaleY(0)` 元素以 transformOrigin 的中心点 Y 缩放到 0, 不改变元素的宽高 |
62 | | transformOrigin | `{ transformOrigin: '50px 50px'}` 元素当前中心点到 x: 50px y: 50px; |
63 |
64 | ## filter 参数
65 |
66 | | 参数名称 | 说明 |
67 | |-------------------|---------------------|
68 | | grayScale | `{ grayScale: 1 }` 元素 filter 灰度到 100%; |
69 | | sepia | `{ sepia: 1 }` 元素 filter 颜色到 100%; |
70 | | hueRotate | `{ hueRotate: '90deg' }` 元素 filter 色相盘旋转 90 度; |
71 | | invert | `{ invert: 1 }` 元素 filter 色值反相到 100% |
72 | | brightness | `{ brightness: 2 }` 元素 filter 亮度到 200% |
73 | | contrast | `{ contrast: 2 }` 对比度到 200% |
74 | | saturate | `{ saturate: 2 }` 饱和度到 200% |
75 | | blur | `{ blur: '20px' }` 模糊到 20px |
76 |
77 | ## svg 参数
78 |
79 | 任何数值为 number 的参数,此处不添加表格,如有需求可查看 [svg 教程](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial);
80 |
81 | > 以上为 tween-one 里的动画可支持参数,如有其它样式可动画或以上有误,烦请 PR 来修改。。
82 |
--------------------------------------------------------------------------------
/language/basic.en-US.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title: Motion
4 | ---
5 |
6 | Animations bring vividness to interfaces and reinforce user experiences.
7 |
8 | ## Motion Values
9 |
10 | - **Smooth interactions:** Animations can make user interactions more natural.
11 |
12 | - **Bring vividness:** Animations can attract users' attention and increase users' motivation to interact by bring more vividness.
13 |
14 | - **Define hierarchies:** Animations can define elements' hierarchies and logical relationships in the most intuitive way.
15 |
16 | - **Provide feedbacks:** Animations can reinforce user experiences by providing motional feedbacks.
17 |
18 | ## Meaningful animation
19 |
20 | To measure whether a animation makes sense, we can assess it by the following criteria:
21 |
22 | - **Justified:** Is this animation necessary? Does this animation help its users to digest the information? An effective animation should not be redundant.
23 |
24 | - **Performant:** Is there any frame loss or lag? An effective animation must be smooth, and must not hurt the overall performance of the product.
25 |
26 |
27 |
--------------------------------------------------------------------------------
/language/basic.zh-CN.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title:
4 | zh-CN: 动效
5 | en-US: Motion
6 | ---
7 |
8 | 界面动效能加强用户认知且增加活力。
9 |
10 | ## 动效价值
11 |
12 | - **增加体验舒适度:** 让用户认知过程更为自然。
13 |
14 | - **增加界面活力:**第一时间吸引注意力,突出重点。
15 |
16 | - **描述层级关系:**体现元素之间的层级与空间关系。
17 |
18 | - **提供反馈、明确意向:**助力交互体验。
19 |
20 | ## 衡量动效意义
21 |
22 | 衡量一个动效是否有意义,我们可以通过以下几个标准来考核:
23 |
24 | - **一个动效的存在是否合理:**是否带有明确的目的性,助力交互体验,没有多余的动效。
25 |
26 | - **动效与性能:**不能出现大幅度波动丢帧或者卡顿现象, 动效的体验须是流畅的,并且不影响产品的性能。
27 |
--------------------------------------------------------------------------------
/language/combined.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 4
3 | title:
4 | zh-CN: 组合
5 | en-US: Combined
6 | ---
7 |
8 | 组合动效是将多种动画效果组合起来运用在单个元素或者界面中的表现方式,吸引用户的注意,让用户快速了解信息的主次关系。ant design 最常用的组合动效有以下三种:
9 | - 单元素组合动画
10 | - 多元素列队动画
11 | - 多元素聚散动画
12 |
13 | ## 单元素组合动效
14 |
15 | 单元素组合动画是指将多个动画参数附加于一个元素上,通过不同的动画参数帮助用户实现自然的认知过程。
16 |
17 | 以下图片展开运用了缩放、位移与透明的动效组合来完成:
18 |
19 |
20 |
21 | ## 多元素队列动效
22 |
23 | 队列一般指同个区块里多个元素的进场或出场,根据元素的排列顺序,有序的进入或依次的退出,实现更为自然的视觉过渡。
24 |
25 | ### 1.单向布局
26 |
27 | 由单例元素横向或纵向形成的布局,依次展示动效出场。
28 |
29 |
30 |
31 | ### 2.区块横纵布局
32 |
33 | 由多行元素组合的一个区块性布局,将界面元素以左上角为起点右下角为终点,设置一个过渡自然的出场顺序
34 |
35 |
36 |
37 | ## 多元素聚散动效
38 |
39 | 以中心点为主向外扩散或汇聚的一个效果,强调主体以及分支之间的关系,能够快速的让用户了解信息的关联性。
40 |
41 |
--------------------------------------------------------------------------------
/language/principle.en-US.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title: Principle
4 | ---
5 |
6 | Different from animations usage in typical front-office applications, animations in enterprise level applications spend a great amount of efforts on reinforcing user interactions and the effectiveness of those interactions. Therefore, we derived three animation design principles from Ant Design's core design language:
7 |
8 |
9 |
10 | ```__react
11 | import Principle from '../site/theme/template/other/Principle';
12 | ReactDOM.render( , mountNode);
13 | ```
14 |
15 |
16 |
17 | ## Natural
18 |
19 | Intuitive animations usually are backed by law of nature. This requires the animations to be smooth so that their users can feel the animations' motion being justified. A natural animation triggers its users with positive user experiences.
20 |
21 | Take button animation as an example, designers image the button as foliage on water - when you press it and release, the leave will slightly go into the water, and then pop back up, creating ripples around itself.
22 |
23 |
24 |
25 | ## Efficient
26 |
27 | Enterprise level applications require highly effective user interactions. So is their animation design - with a transition time as minimal as possible.
28 |
29 | For example, compared to appearing animations, disappearing animations should not attract too much attention from their users. They just need to be concise and clear. Therefore, disappearing animations are configured to swing out with faster velocity and no disappearing delay between each list items - they disappear all at the same time as one unit.
30 |
31 |
32 |
33 | ## Restrain
34 |
35 | Avoid dramatic and complicated animations. A good animation will get the job done instead of frustrating its users.
36 |
37 | For example, when a user expands a menu, his main focus is on the menu content, not the direction change of the arrow icon on the right. Therefore, the animation doesn't need to be very complicated and distracting; it changes just enough to indicate the transition.
38 |
39 |
--------------------------------------------------------------------------------
/language/principle.zh-CN.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title:
4 | zh-CN: 原则
5 | en-US: Principle
6 | ---
7 |
8 | 在企业级应用的产品设计中,使用动效和前台类产品有很大的不同,助力交互行为和增强信息认知显得尤为重要,在 ant design 设计价值观的基础之上,我们衍生出动效设计的三原则:
9 |
10 |
11 |
12 | ```__react
13 | import Principle from '../site/theme/template/other/Principle';
14 | ReactDOM.render( , mountNode);
15 | ```
16 |
17 |
18 |
19 | ## 自然
20 |
21 | 自然的动效背后体现的是自然运动规律。这就要求动效在转换时保证视觉上的连贯性,让用户感知到这个动作是自然的,是能够引起共鸣的。
22 |
23 | 以 button 的动效设计为例,设计师将其想像成一片树叶飘浮在水面之上,当你去触碰它时,叶子会下浮再反弹,然后出现涟漪效果。
24 |
25 |
26 |
27 | ## 高效
28 |
29 | 企业级应用追求的是高效的用户体验,与之对应的动效设计也应如此,尽量节省过渡的时间,快速完成过渡的动画效果。
30 |
31 | 举个例子,在出场与进场的动效里,出场不用大张旗鼓的去吸引用户的注意力,而是做到简单清晰即可。所以我们的出场时间采用了更快的速度,同时也不设置队列依次出场的形式,只需要整块直接消失即可。
32 |
33 |
34 |
35 | ## 克制
36 |
37 | 尽量避免夸张的动效,做有意义的事,不去做太多的修饰而干扰用户。
38 |
39 | 如我们的 Menu,在展开时,注重的是菜单的内容,而右侧的 icon 切换并不是主要元素,不需要过度强调去分散用户的注意,所以只需在不经意间切换,明确指示变化即可。
40 |
41 |
--------------------------------------------------------------------------------
/language/space.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 3
3 | title:
4 | zh-CN: 空间
5 | en-US: Space
6 | ---
7 |
8 | 现实空间里,物体存在远小近大的原则,运动则有远慢近快。在动效设计时,处理和空间相关的话题时,我们需要考虑两方面的因素:
9 |
10 | - **视差:**例如汽车在公路上行驶,离汽车越近的物体,移动速度越接近汽车的速率。以行进中的汽车为例,汽车所在的点为 X 轴的基准点,离基准点越远时,速度就越慢。动效设计中同样存在这个原则,元素的空间距离会影响动画效果,从而影响动效设计的决策。
11 | - **大小:**遵循远处的物体小,近处的物体大的原则。
12 |
13 |
14 | ## 空间示意图
15 |
16 |
17 |
18 |
19 | ## 视差
20 |
21 | 在下面这个案例中,考虑动效设计时,首先应将界面中涉及到动画的元素进行分层,为界面中不同的元素假设不同的距离。而鼠标所在位置作为基准点。建立了这样的空间层次之后,有效地给每层元素赋予不同的参数,就能摸拟自然的视差效果。
22 |
23 |
24 |
25 | ### 动态效果
26 |
27 | 以距离的差距来体现视差。
28 |
29 |
30 |
31 |
32 |
33 |
34 | 以时间的差距来体现视差,详细查看动效展示里的[详细说明切换](/exhibition/demo/detail-switch)。
35 |
36 |
37 |
38 | ## 大小
39 |
40 | 在下面这个案例中,包含两层抽屉式的的界面展开,遵循远小近大的原则,当近处层级出现时,底部的层级做适当的缩小,体现出空间感。
41 |
42 |
--------------------------------------------------------------------------------
/language/speed.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | title:
4 | zh-CN: 速度
5 | en-US: Speed
6 | ---
7 |
8 | 速度的快或慢取决于时间与缓动,相同的距离,时间越短速度则越快,而缓动则是能将同一段时间划分快与慢的区域。
9 |
10 | ## 时间
11 |
12 | 在企业级应用的设计中,动效需要在尽可能短的时间内有效的完成过渡。那么如何把握这个时间的长短呢?伦敦城市学院神经学创立者 [Davina Bristow](http://www.ucl.ac.uk/media/library/blinking) 曾提出, 眨眼是人体最快的潜意识动作,大多数人每分钟眨眼 15 次,眨眼平均持续 100-150 毫秒;所以我们将这个时间段定义成 Ant Design 动效的基本时间单位。
13 |
14 | ### Ant Design 组件里的基本时间单位
15 |
16 | 最快时间: 100ms, 基本时间: 200ms, 较大时间:300ms... 100 的倍增方式。
17 |
18 |
19 |
20 | ### 示例演示
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ### 页面转换或其它的时间单位
30 |
31 | 在页面的动效里,我们运用了 150ms 为最小单位。
32 |
33 | 最快时间: 150ms, 基本时间: 300ms, 平滑时间:450ms, 较大时间: 600ms... 150 的倍增方式
34 |
35 |
36 |
37 | > 示例可参考模板编辑里的模板的动效
38 |
39 | ## 缓动
40 |
41 | 按照物理学的解释,如果在任何相等的时间内,元素在动画过程中每个点的距离都是相等的,那么,元素的运动就是匀速运动;如果在任何相等的时间内,元素在动画过程中点的距离不相等的,那么,元素的运动就是非匀速运动,非匀速运动又分为加速运动和减速运动。速度由慢到快的运动称加速运动;速度由快到慢的运动称减速运动。
42 |
43 | ### 匀速运动
44 |
45 | 比如:一秒有30帧的动画,那么这动画就是由 30 张图片组成,只是每张图片里的元素指定的参数不同, 如下图:
46 |
47 |
48 |
49 |
线性动画结构图(适合于机械或环状运动)
50 |
51 |
52 | ### 非匀速运动
53 |
54 | 结合自然运动的规律,那物体运动在时间栅格中具有不同运动速率和出场,动画停止与启动都不是瞬间完成的,当物体突然移动或停止,会显的很不自然,因它需要一段缓冲的时间来加速或减速,如下图:
55 |
56 |
57 |
58 |
前后缓动动画结构图(自然的运动结构)
59 |
60 |
61 |
62 | 如对缓动函数不了解的可参考:
缓动函数 。
63 |
64 |
65 | > 注:使用缓动时也需要结合元素所附于什么物体或使用场景来使用,如卡通可用弹性缓动,如 `Elastic`, 稳重性比较强建议使用基本的缓动函数 `Cubic`。
66 |
67 | ### 动态效果
68 |
69 | 以下效果为基本的缓动效果,可查看以下示例,鼠标 hover 时自动播放动画。
70 |
71 | > 需要注意:如果在可视窗口中消失的,属于点到点之间的运动,建议使用前后缓动,同理可视窗口中出现也一样。
72 |
73 | ```__react
74 | import EaseExplain from '../site/theme/template/other/EaseExplain';
75 | ReactDOM.render(
82 | 单物体可视范围内点到点之间的运动,采用的是
83 | ease-in-out
84 | , mountNode);
85 | ```
86 |
87 | ```__react
88 | import EaseExplain from '../site/theme/template/other/EaseExplain';
89 | ReactDOM.render(
95 | 单物体进入可视范围的运动,采用的是
96 | ease-out
97 | , mountNode);
98 | ```
99 |
100 | ```__react
101 | import EaseExplain from '../site/theme/template/other/EaseExplain';
102 | ReactDOM.render(
107 | 单物体出可视范围的运动,采用的是
108 | ease-in
109 | , mountNode);
110 | ```
111 |
112 |
--------------------------------------------------------------------------------
/language/transition.en-US.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 5
3 | title: Transition
4 | ---
5 |
6 | > The transition is a more complex combination of animation, is an entry and leave effect for the current element, transition requires multiple different animations to complete.
7 |
8 | Our Gray Matter are wired to react to dynamic things like movement,shape change and colour change. Transitions smooth out the jarring world of the Web, making changes appear more natural. The main purpose for Transitions is to provide an engaging interface and reinforce communication.
9 |
10 | ## Visual coherence three elements
11 |
12 | - **Adding**: The added elements should inform the users how to use, and the modified elements should be recognized.
13 |
14 | - **Receding**: The irrelevant page elements should be removed properly.
15 |
16 | - **Normal**: The elements without any change on the page can be safely ignored.
17 |
18 | ## Maintain Context While Changing Views
19 |
20 | Slide In and Slide Out: Create an illusion of virtual space.
21 |
22 | ### Pages transition
23 |
24 | Slide In and Slide Out: Create an illusion of virtual space.
25 |
26 |
27 |
28 | ### Carousel
29 |
30 | Carousels are great for extending virtual space.
31 |
32 |
33 |
34 |
35 | ### Accordion
36 |
37 | Accordion helps maintain context while switching views.
38 |
39 |
40 |
41 | ## Explain What Just Happened
42 |
43 | Visualize user actions to enhance the user's perception of operational behavior and also to recognize elemental content;
44 |
45 | In a list or table, when changing an object, add animation to appear and disappear, to prompt the user for the event that was just being operated.
46 |
47 | ### Adding an Object
48 |
49 | Add an object in the table or chart.
50 |
51 |
52 |
53 | ### Deleting an Object
54 |
55 | Delete an object in the table or chart.
56 |
57 |
58 |
59 | ### Modifying an Object
60 |
61 | Modify an object in the table or chart.
62 |
63 |
64 |
65 | ### Calling out an Object
66 |
67 | Click the page element and call out a new object.
68 |
69 |
70 |
71 | ## Improve Perceived Performance
72 |
73 | If actual performance can hardly improved, there is a difference between actual performance and perceived performance. Diverting the user's attention is a good way to improve the perceived time an operation takes.
--------------------------------------------------------------------------------
/language/transition.zh-CN.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 5
3 | title:
4 | zh-CN: 过渡
5 | en-US: Transition
6 | ---
7 |
8 | > 过渡是更复杂的组合动画效果,组合动画是针对当前的元素进行的一个进出场效果,而过渡往往需要多个不同的动画来完成一段多个页面中间的过渡。
9 |
10 | 人脑灰质(Gray Matter)会对动态的事物(eg:移动、形变、色变等)保持敏感。 在界面中,适当的加入一些过渡效果,能让界面保持生动,同时也能增强用户和界面的沟通。
11 |
12 | ## 视觉连贯性三元素
13 |
14 | - **Adding**: 新加入的信息元素应被告知如何使用,从页面转变的信息元素需被重新识别。
15 |
16 | - **Receding**: 与当前页无关的信息元素应采用适当方式移除。
17 |
18 | - **Normal**: 指那些从转场开始到结束都没有发生变化的信息元素。
19 |
20 | ## 视图变化时保持上下文
21 |
22 | 视图变化时保持上下文
23 |
24 | ### 页面间切换
25 |
26 | 在视图变化时保持上下文; 滑入与滑出: 可以有效构建虚拟空间。
27 |
28 |
29 |
30 | ### 传送带切换(走马灯)
31 |
32 | 可极大地扩展虚拟空间。
33 |
34 |
35 |
36 |
37 | ### 折叠窗口
38 |
39 | 在视图切换时,有助于保持上下文,同时也能拓展虚拟空间。
40 |
41 |
42 |
43 | ## 解释刚刚发生了什么
44 |
45 | 将用户操作可视化, 来增强用户对操作行为的感知度, 同时也能对元素内容的认知;
46 |
47 | 在列表或表格中, 变更一个对象时, 加入对象出现与消失效果, 以提示用户所操作的行为。
48 |
49 | ### 对象增加
50 |
51 | 增加后, 用一个动画和背景色来区分新增元素, 过一段时间再恢复正常。
52 |
53 |
54 |
55 | ### 对象删除
56 |
57 | 删除后, 用移出的效果来做删除的效果。
58 |
59 |
60 |
61 | ### 对象更改
62 |
63 | 用户更改了内容时, 在保存后, 在修改过的位置出现背景色, 表示该对象发生过变更, 然后背景色持续一断时间再消失, 恢复正常。
64 |
65 |
66 |
67 | ### 弹出框呼出
68 |
69 | 从页面的某个按钮呼出弹出框时, 弹框从按钮处呼起, 可提示用户弹框与按钮的关系。
70 |
71 |
72 |
73 | ## 改善感知性能
74 |
75 | 当无法有效提升『实际性能』时,可以考虑适当转移用户的注意力,来缩短某项操作的感知时间,改善感知性能。
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ant-motion",
3 | "version": "1.7.0",
4 | "title": "Ant Motion",
5 | "description": "react animation component",
6 | "homepage": "http://motion.ant.design/",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/ant-design/ant-motion"
10 | },
11 | "license": "MIT",
12 | "dependencies": {
13 | "rc-animate": "^2.6.0",
14 | "rc-banner-anim": "^2.2.3",
15 | "rc-drawer": "^3.0.2",
16 | "rc-queue-anim": "^1.7.0",
17 | "rc-scroll-anim": "^2.6.1",
18 | "rc-texty": "^0.2.0",
19 | "rc-tween-one": "^2.4.0"
20 | },
21 | "devDependencies": {
22 | "antd": "^3.13.2",
23 | "antd-tools": "^7.0.0",
24 | "babel-eslint": "^10.0.1",
25 | "bisheng": "^1.1.0",
26 | "bisheng-plugin-antd": "^1.0.0",
27 | "bisheng-plugin-description": "^0.1.4",
28 | "bisheng-plugin-react": "^1.0.0",
29 | "bisheng-plugin-toc": "^0.4.4",
30 | "core-js": "^3.0.1",
31 | "cross-env": "^7.0.0",
32 | "enquire-js": "^0.2.1",
33 | "eslint": "^7.1.0",
34 | "eslint-config-airbnb": "^18.0.0",
35 | "eslint-loader": "^3.0.0",
36 | "eslint-plugin-babel": "^5.1.0",
37 | "eslint-plugin-compat": "^3.1.1",
38 | "eslint-plugin-import": "^2.14.0",
39 | "eslint-plugin-jsx-a11y": "^6.1.2",
40 | "eslint-plugin-markdown": "^1.0.0-beta.6",
41 | "eslint-plugin-react": "^7.11.1",
42 | "eslint-tinker": "^0.5.0",
43 | "jsonml.js": "^0.1.0",
44 | "pre-commit": "1.x",
45 | "prop-types": "15.x",
46 | "react": "^16.4.0",
47 | "react-document-title": "^2.0.1",
48 | "react-dom": "^16.4.0",
49 | "react-github-button": "^0.1.11",
50 | "react-intl": "^3.2.0",
51 | "react-router": "~5.1.2",
52 | "react-sublime-video": "^0.2.0",
53 | "stylelint": "^13.1.0",
54 | "stylelint-config-standard": "^20.0.0",
55 | "@typescript-eslint/eslint-plugin": "^2.15.0"
56 | },
57 | "pre-commit": [
58 | "lint"
59 | ],
60 | "scripts": {
61 | "start": "rm -rf _site && cross-env NODE_ENV=development bisheng start -c ./site/bisheng.config.js",
62 | "build": "rm -rf _site && cross-env NODE_ENV=production bisheng build -c ./site/bisheng.config.js",
63 | "site": "npm run build",
64 | "deploy": "npm run site && cp CNAME _site && bisheng gh-pages --push-only",
65 | "lint": "npm run lint:es && npm run lint:style",
66 | "lint:es": "eslint --fix --ext '.js,.jsx' site",
67 | "lint:style": "stylelint --fix \"site/**/*.less\" --syntax less",
68 | "lint:demo": "cross-env RUN_ENV=DEMO eslint ./ --ext '.md' -c ./.eslintrc.js",
69 | "test": "npm run lint"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/site/bisheng.config.js:
--------------------------------------------------------------------------------
1 |
2 | const path = require('path');
3 | const replaceLib = require('antd-tools/lib/replaceLib');
4 |
5 | const isDev = process.env.NODE_ENV === 'development';
6 |
7 | const antdImport = ['import', { libraryName: 'antd', style: true }];
8 |
9 | function alertBabelConfig(rules) {
10 | rules.forEach((rule) => {
11 | if (rule.loader && rule.loader.indexOf('babel-loader') >= 0) {
12 | if (rule.options.plugins.indexOf(replaceLib) === -1) {
13 | rule.options.plugins.push(replaceLib);
14 | }
15 | if (rule.options.plugins.indexOf(antdImport) === -1) {
16 | rule.options.plugins.push(antdImport);
17 | }
18 | /* rule.options.plugins = rule.options.plugins.filter(plugin =>
19 | !plugin.indexOf || plugin.indexOf('babel-plugin-add-module-exports') === -1
20 | ); */
21 | } else if (rule.use) {
22 | alertBabelConfig(rule.use);
23 | }
24 | });
25 | }
26 |
27 | module.exports = {
28 | source: {
29 | language: './language',
30 | components: './components',
31 | exhibition: './exhibition',
32 | },
33 | theme: './site/theme',
34 | themeConfig: {
35 | root: '/',
36 | language: {
37 | 动效: 0,
38 | Motion: 0,
39 | },
40 | },
41 | htmlTemplate: './site/theme/static/index.html',
42 | port: 8111,
43 | filePathMapper(filePath) {
44 | if (filePath === '/index.html') {
45 | return ['/index.html', '/index-cn.html'];
46 | }
47 | if (filePath.endsWith('/index.html')) {
48 | return [filePath, filePath.replace(/\/index\.html$/, '-cn/index.html')];
49 | }
50 | if (filePath !== '/404.html' && filePath !== '/index-cn.html') {
51 | return [filePath, filePath.replace(/\.html$/, '-cn.html')];
52 | }
53 | return filePath;
54 | },
55 | doraConfig: {
56 | verbose: true,
57 | },
58 | lessConfig: {
59 | javascriptEnabled: true,
60 | },
61 | webpackConfig(config) {
62 | config.resolve.alias = {
63 | site: path.join(process.cwd(), 'site'),
64 | 'react-router': 'react-router/umd/ReactRouter',
65 | };
66 |
67 | // eslint-disable-next-line
68 | config.externals = {
69 | 'react-router-dom': 'ReactRouterDOM',
70 | };
71 | if (isDev) {
72 | // eslint-disable-next-line
73 | config.devtool = 'source-map';
74 | }
75 | alertBabelConfig(config.module.rules);
76 | return config;
77 | },
78 | devServerConfig: {
79 | public: process.env.DEV_HOST || 'localhost',
80 | disableHostCheck: !!process.env.DEV_HOST,
81 | },
82 |
83 | htmlTemplateExtraData: {
84 | isDev,
85 | },
86 | };
87 |
--------------------------------------------------------------------------------
/site/theme/en-US.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | locale: 'en-US',
4 | messages: {
5 | 'app.header.menu.exhibition': 'Exhibition',
6 | 'app.header.menu.language': 'Language',
7 | 'app.header.menu.components': 'Components',
8 | 'app.header.menu.templates': 'Templates',
9 | 'app.header.lang': '中文',
10 | 'app.home.introduce': 'Use Ant Motion to quickly use animations in the React framework.',
11 | 'app.home.introduce2': 'We offer single, combined and complete animations solutions.',
12 | 'app.home.learn-more': 'Learn More',
13 | 'app.home.enter-editor': 'Enter Editor',
14 | 'app.home.page1.title': 'Animation easier',
15 | 'app.home.page1.content': 'In the React framework, you only need a simple piece of code to achieve animation effects, \nwhich can improve your work efficiency.',
16 | 'app.home.page2.content': 'With Ant Motion, you can quickly achieve animation effects.\n With different interaction modes, you can apply directly to your project.',
17 | 'app.home.page2.learn-more': 'Learn More',
18 | 'app.home.page3.title': 'Add interesting animation to your product',
19 | 'app.home.page3.content': 'With more friendly interaction, let the animate shuttle between different elements,\n so that the product can better talk to the user.',
20 | 'app.home.page3.button': 'Quick Start',
21 | 'app.details.code': 'Code Snippet',
22 | 'app.content.edit-page': 'Edit this page on GitHub!',
23 | 'app.content.components-exp': 'Example',
24 | 'app.footer.repo': 'GitHub',
25 | 'app.footer.template': 'Template GitHub',
26 | 'app.footer.chinamirror': 'China Mirror 🇨🇳',
27 | 'app.footer.scaffolds': 'Scaffold Market',
28 | 'app.footer.links': 'Sites',
29 | 'app.footer.data-vis': 'Data Visualization',
30 | 'app.footer.eggjs': 'Enterprise Node Framework',
31 | 'app.footer.landing': 'Landing Templates',
32 | 'app.footer.kitchen': 'Sketch Toolkit',
33 | 'app.footer.umi': 'React Application Framework',
34 | 'app.footer.dva': 'Data Flow Framework',
35 | 'app.footer.antd-library': 'Axure library',
36 | 'app.footer.design-platform': 'Ant Financial Design Platform',
37 | 'app.footer.antux': 'Sitemap Template',
38 | 'app.footer.community': 'Community',
39 | 'app.footer.issues': 'Issues',
40 | 'app.footer.work-with-us': 'Work with Us',
41 | 'app.footer.author': 'Created by AFX',
42 | 'app.footer.resources': 'Resources',
43 | 'app.footer.more-product': 'More Products',
44 | 'app.footer.yuque': 'YuQue',
45 | 'app.footer.yuque.slogan': 'Write your document as a team',
46 | 'app.footer.fengdie': 'FengDie',
47 | 'app.footer.fengdie.slogan': 'Mobile web app builder',
48 | 'app.footer.seeconf': 'Seeking Experience & Engineering Conference',
49 | 'app.footer.xcloud': 'Ant Experience Cloud',
50 | },
51 | };
52 |
--------------------------------------------------------------------------------
/site/theme/index.js:
--------------------------------------------------------------------------------
1 | const Article = './template/Content/Article';
2 | const ComponentDoc = './template/Content/ComponentDoc';
3 | const Exhibition = './template/Exhibition/index';
4 | const Details = './template/Exhibition/Details';
5 | const path = require('path');
6 |
7 | const homeTmpl = './template/Home/index';
8 | // const contentTmpl = './template/Content/index';
9 |
10 | function pickerGenerator(module = 'language/') {
11 | const tester = new RegExp(`^${module}`);
12 | return (markdownData) => {
13 | const { filename } = markdownData.meta;
14 | if (tester.test(filename) && !/\/demo$/.test(path.dirname(filename))) {
15 | return {
16 | meta: markdownData.meta,
17 | };
18 | }
19 | return null;
20 | };
21 | }
22 |
23 | module.exports = {
24 | lazyLoad(nodePath, nodeValue) {
25 | if (typeof nodeValue === 'string') {
26 | return true;
27 | }
28 | return nodePath.endsWith('/demo');
29 | },
30 | pick: {
31 | language: pickerGenerator(),
32 | components: pickerGenerator('components'),
33 | api: pickerGenerator('components'),
34 | },
35 | plugins: [
36 | 'bisheng-plugin-description',
37 | 'bisheng-plugin-toc?maxDepth=2&keepElem',
38 | 'bisheng-plugin-antd',
39 | 'bisheng-plugin-react?lang=__react',
40 | ],
41 | routes: {
42 | path: '/',
43 | component: './template/Layout/index',
44 | indexRoute: { component: homeTmpl },
45 | childRoutes: [
46 | {
47 | path: 'index-cn',
48 | component: homeTmpl,
49 | },
50 | {
51 | path: '/exhibition/',
52 | component: Exhibition,
53 | },
54 | {
55 | path: '/exhibition-cn/',
56 | component: Exhibition,
57 | },
58 | {
59 | path: '/exhibition/demo/:children',
60 | component: Details,
61 | },
62 | { path: '/language/:children', component: Article },
63 | {
64 | path: '/components/:children',
65 | component: ComponentDoc,
66 | },
67 | { path: '/api/:children', component: Article },
68 | /* { path: '/exhibition/', component: Exhibition },
69 | { path: '/exhibition/demo/:contentName', component: Details },
70 | { path: '/getting/:contentName', component: Article },
71 | { path: '/components/:contentName', component: ComponentDoc },
72 | { path: '/language/:contentName', component: Article },
73 | { path: '/api/tween-one', component: Article },
74 | { path: '/api/animate', component: Article },
75 | { path: '/api/queue-anim', component: Article },
76 | { path: '/api/scroll-anim', component: Article },
77 | { path: '/api/banner-anim', component: Article },
78 | { path: '/api/texty', component: Article }, */
79 | ],
80 | },
81 | };
82 |
--------------------------------------------------------------------------------
/site/theme/static/custom.less:
--------------------------------------------------------------------------------
1 | @import "~antd/lib/style/themes/default.less";
2 |
3 | @text-color-home: #9FB0C7;
4 | // @text-color-home-banner: #3761b5;
5 | @text-color-light: #fff;
6 | @text-color-dark: #3E3E3E;
7 |
8 | @bg-color: #F6F7F8;
9 | @nav-color: #070B20;
10 | @nav-link-active-color: @text-color-light;
11 | @nav-link-color: #656669;
12 | @bar-color: #FBFBFB;
13 | @footer-bg-color: @bar-color;
14 | @footer-link-color: #8A8A8A;
15 |
16 | @link-color: @primary-color;
17 |
18 | @link-hover-color: tint(@link-color, 20%);
19 |
20 | @link-active-color: shade(@link-color, 5%);
21 |
22 | @link-hover-decoration: none;
23 |
24 | @line-color: #E8E8E8;
25 | @line-deep-color: #979797;
26 | @disabled-color: #5B5B5B;
27 | @list-disabled-color: #ccc;
28 |
29 | @page-bg-color: @text-color-light;
30 |
31 | @shadow-color: rgba(0, 0, 0, 0.15);
32 |
33 | @title-color: @text-color-dark;
34 | @title-bg-color: #364768;
35 | @title-color-exhibition: #666;
36 |
37 | @scrollbar-color: #E2E2E2;
38 |
39 | @demo-text-color: #8A8A8A;
40 |
41 | @demo-title-color: #636F84;
42 | @demo-color: fade(#4FA9FB, 60);
43 |
44 | @template-bg-color: #333;
45 | @template-bg-color-light: #ECECEC;
46 | @template-nav-bg-color: fade(@template-bg-color, 95%);
47 | @template-text-color: #CCC;
48 | @template-text-title-color: #BCBCBC;
49 | @template-text-color-light: #FFF;
50 |
51 | // markdown 样式颜色;
52 |
53 | @markdown-title-color: #404040;
54 | @markdown-fonts-color: #404040;
55 |
56 | @animate-duration: .45s;
57 |
58 | // 详细页图片或框框的样式;
59 | .page-shadow() {
60 | box-shadow: 0 5px 10px @shadow-color;
61 | }
62 |
63 | .page-pro() {
64 | border-radius: 6px;
65 | border: 1px solid @line-color;
66 | transform: translateY(0);
67 | position: relative;
68 | will-change: transform, box-shadow;
69 | transition: transform .3s @ease-out, box-shadow .3s @ease-out;
70 | &:hover {
71 | .page-shadow();
72 | transform: translateY(-4px);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/site/theme/static/demolayout.less:
--------------------------------------------------------------------------------
1 | @import './custom';
2 |
3 | @demo: demo-layout;
4 | .@{demo} {
5 | margin: 2em auto;
6 | position: relative;
7 | width: 100%;
8 | }
9 |
10 | @code: code-box;
11 | .@{code}-wrapper {
12 | & > h2 {
13 | font-size: 16px;
14 | margin: 20px auto 15px;
15 | color: @markdown-title-color;
16 | font-weight: 400;
17 | }
18 | .@{code} {
19 | // .page-pro();
20 | // transition: opacity @animate-duration @ease-out, transform @animate-duration @ease-out, box-shadow @animate-duration @ease-out !important;
21 | border: 1px solid @line-color;
22 | overflow: hidden;
23 | margin: 30px auto;
24 | min-height: 220px;
25 | background: #fff;
26 | border-radius: 3px;
27 | &-demo {
28 | float: right;
29 | width: 40%;
30 | position: relative;
31 | height: 100%;
32 | min-height: 220px;
33 | padding: 10px;
34 | background: #fff;
35 | }
36 | &-code {
37 | overflow: hidden;
38 | border-right: 1px solid @line-color;
39 | & pre {
40 | padding: 0 !important;
41 | margin: 0 !important;
42 | border-radius: 0;
43 | overflow: auto;
44 | border: none;
45 | height: 100%;
46 | &.css {
47 | border-top: 1px solid @line-color;
48 | }
49 | & code {
50 | display: block;
51 | padding: 1em;
52 | border-radius: 0;
53 | width: 100%;
54 | background: none;
55 | }
56 | }
57 | }
58 |
59 | &-bar {
60 | height: 20px;
61 | border-top: 1px solid @line-color;
62 | background: @bar-color;
63 | position: relative;
64 | text-align: center;
65 | line-height: 20px;
66 | cursor: pointer;
67 | }
68 | }
69 | &.vertical {
70 | .@{code} {
71 | &-demo {
72 | float: none;
73 | width: 100%;
74 | }
75 | &-code {
76 | border-right: none;
77 | border-top: 1px solid @line-color;
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/site/theme/static/exhibition.less:
--------------------------------------------------------------------------------
1 | @import 'custom';
2 |
3 | @exhibition: exhibition-list;
4 | .@{exhibition} {
5 | & > li {
6 | width: 45%;
7 | display: inline-block;
8 | text-align: center;
9 | margin-bottom: 40px;
10 | &:nth-child(2n) {
11 | margin-left: 10%;
12 | }
13 | & a, & a img {
14 | display: block;
15 | }
16 | & h3 {
17 | line-height: 42px;
18 | color: @title-color-exhibition;
19 | background: @page-bg-color;
20 | }
21 | .page-pro();
22 | border: none;
23 | border-radius: 0;
24 | }
25 | }
26 |
27 | @details: exhibition-details;
28 | .@{details} {
29 | margin-bottom: 60px;
30 | &-demo {
31 | margin-bottom: 40px;
32 | }
33 | .replay-button {
34 | float: right;
35 | margin: -85px 10px;
36 | position: relative;
37 | bottom: 0;
38 | right: 0;
39 | }
40 | & > pre {
41 | max-height: 600px;
42 | overflow: auto;
43 | }
44 | & h3 {
45 | margin: 1em 0 .6em 0;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/site/theme/static/footer.less:
--------------------------------------------------------------------------------
1 | @import "./custom.less";
2 | @site-text-color: #314659;
3 | @padding-space: 144px;
4 | @border-color: rgba(229, 231, 235, 100);
5 | footer.dark {
6 | background-color: #000;
7 | color: rgba(255, 255, 255, 0.65);
8 | a {
9 | color: rgba(255, 255, 255, 0.9);
10 | }
11 | h2 {
12 | color: rgba(255, 255, 255, 1);
13 | & >span {
14 | color: rgba(255, 255, 255, 1);
15 | }
16 | }
17 | .bottom-bar {
18 | overflow: hidden;
19 | }
20 | }
21 |
22 | footer {
23 | clear: both;
24 | font-size: 14px;
25 | background: #fff;
26 | position: relative;
27 | z-index: 100;
28 | color: @site-text-color;
29 | box-shadow: 0 1000px 0 1000px #fff;
30 | .ant-row {
31 | text-align: center;
32 | width: 100%;
33 | max-width: 1200px;
34 | padding: 86px 24px 93px 24px;
35 | margin: auto;
36 | .footer-center {
37 | display: inline-block;
38 | text-align: left;
39 | >h2 {
40 | font-size: 16px;
41 | margin: 0 auto 24px;
42 | font-weight: 500;
43 | position: relative;
44 | >.title-icon {
45 | width: 27px;
46 | margin-right: 16px;
47 | }
48 | >.anticon {
49 | font-size: 16px;
50 | position: absolute;
51 | left: -22px;
52 | top: 3px;
53 | color: #aaa;
54 | }
55 | }
56 | >div {
57 | margin: 12px 0;
58 | }
59 | }
60 | }
61 | .footer-wrap {
62 | position: relative;
63 | width: 100%;
64 | border-bottom: 1px solid rgba(255, 255, 255, 0.25);
65 | }
66 | .bottom-bar {
67 | text-align: center;
68 | padding: 16px 0;
69 | margin: 0;
70 | line-height: 32px;
71 | overflow: hidden;
72 | font-family: "Avenir", @font-family, sans-serif;
73 | font-size: 16px;
74 | a {
75 | color: rgba(255, 255, 255, 0.65);
76 | margin-left: 4px;
77 | &:hover {
78 | color: #fff;
79 | }
80 | }
81 | .translate-button {
82 | text-align: left;
83 | }
84 | .heart {
85 | color: #f73f51;
86 | font-size: 22px;
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/site/theme/static/global.less:
--------------------------------------------------------------------------------
1 | @import 'custom';
2 | html, body {
3 | font-family: "PingFang SC", "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", "\5FAE\8F6F\96C5\9ED1", Arial, sans-serif;
4 | }
5 | body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
6 | margin: 0;
7 | padding: 0;
8 | }
9 |
10 | ul,
11 | ol {
12 | list-style: none;
13 | }
14 |
15 | body video {
16 | display: block;
17 | }
18 |
19 | .text-center {
20 | text-align: center;
21 | }
22 |
23 | a {
24 | transition: color @animate-duration @ease-out;
25 | }
26 |
27 | h1, h2, h3, h4 {
28 | color: @title-color;
29 | }
30 |
31 | #react-content {
32 | width: 100%;
33 | overflow: hidden;
34 | }
35 |
36 | #page-404 {
37 | min-height: 680px;
38 | text-align: center;
39 | padding-top: 10%;
40 | color: #999;
41 | & h1 {
42 | text-shadow: -1px -1px 4px #666;
43 | font-size: 200px;
44 | }
45 | }
46 |
47 | // 修改 nprogress load 色
48 | #nprogress {
49 | & .bar {
50 | background: @primary-color;
51 | }
52 | & .peg {
53 | box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;
54 | }
55 | & .spinner-icon {
56 | border-top-color: @primary-color;
57 | border-left-color: @primary-color;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/site/theme/static/highlight.less:
--------------------------------------------------------------------------------
1 | /**
2 | * prism.js default theme for JavaScript, CSS and HTML
3 | * Based on dabblet (http://dabblet.com)
4 | * @author Lea Verou
5 | */
6 |
7 | pre code {
8 | display: block;
9 | background: white;
10 | color: #8a8a8a;
11 | line-height: 1.7;
12 | padding: 10px 15px;
13 | border-radius: 6px;
14 | font-size: 13px;
15 | white-space: pre;
16 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
17 | }
18 |
19 | code[class*="language-"],
20 | pre[class*="language-"] {
21 | color: black;
22 | text-shadow: 0 1px white;
23 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
24 | direction: ltr;
25 | text-align: left;
26 | white-space: pre;
27 | word-spacing: normal;
28 | word-break: normal;
29 | word-wrap: normal;
30 | line-height: 1.5;
31 |
32 | -moz-tab-size: 4;
33 | -o-tab-size: 4;
34 | tab-size: 4;
35 |
36 | -webkit-hyphens: none;
37 | -moz-hyphens: none;
38 | -ms-hyphens: none;
39 | hyphens: none;
40 | }
41 |
42 | pre[class*="language-"]::-moz-selection,
43 | pre[class*="language-"] ::-moz-selection,
44 | code[class*="language-"]::-moz-selection,
45 | code[class*="language-"] ::-moz-selection {
46 | text-shadow: none;
47 | background: #b3d4fc;
48 | }
49 |
50 | pre[class*="language-"]::selection,
51 | pre[class*="language-"] ::selection,
52 | code[class*="language-"]::selection,
53 | code[class*="language-"] ::selection {
54 | text-shadow: none;
55 | background: #b3d4fc;
56 | }
57 |
58 | @media print {
59 | code[class*="language-"],
60 | pre[class*="language-"] {
61 | text-shadow: none;
62 | }
63 | }
64 |
65 | /* Code blocks */
66 | pre[class*="language-"] {
67 | padding: 1em;
68 | margin: .5em 0;
69 | overflow: auto;
70 | }
71 |
72 | :not(pre) > code[class*="language-"],
73 | pre[class*="language-"] {
74 | // background: #f5f2f0;
75 | }
76 |
77 | /* Inline code */
78 | :not(pre) > code[class*="language-"] {
79 | padding: .1em;
80 | border-radius: .3em;
81 | white-space: normal;
82 | }
83 |
84 | .token.comment,
85 | .token.prolog,
86 | .token.doctype,
87 | .token.cdata {
88 | color: slategray;
89 | }
90 |
91 | .token.punctuation {
92 | color: #999;
93 | }
94 |
95 | .namespace {
96 | opacity: .7;
97 | }
98 |
99 | .token.property,
100 | .token.tag,
101 | .token.boolean,
102 | .token.number,
103 | .token.constant,
104 | .token.symbol,
105 | .token.deleted {
106 | color: #ff4848;
107 | }
108 |
109 | .token.selector,
110 | .token.attr-name,
111 | .token.string,
112 | .token.char,
113 | .token.builtin,
114 | .token.inserted {
115 | color: #6fcaa7;
116 | }
117 |
118 | .token.operator,
119 | .token.entity,
120 | .token.url,
121 | .language-css .token.string,
122 | .style .token.string {
123 | color: #daa232;
124 | background: hsla(0, 0%, 100%, .5);
125 | }
126 |
127 | .token.atrule,
128 | .token.attr-value,
129 | .token.keyword {
130 | color: #00adf3;
131 | }
132 |
133 | .token.function {
134 | color: #f06351;
135 | }
136 |
137 | .token.regex,
138 | .token.important,
139 | .token.variable {
140 | color: #e90;
141 | }
142 |
143 | .token.important,
144 | .token.bold {
145 | font-weight: bold;
146 | }
147 |
148 | .token.italic {
149 | font-style: italic;
150 | }
151 |
152 | .token.entity {
153 | cursor: help;
154 | }
155 |
--------------------------------------------------------------------------------
/site/theme/static/logo-demo.less:
--------------------------------------------------------------------------------
1 | @import "./custom";
2 |
3 | @demo: logo-demo;
4 |
5 | .@{demo} {
6 | width: 100%;
7 | height: 100%;
8 | position: relative;
9 | & .point-wrapper {
10 | position: absolute;
11 | }
12 | & .point {
13 | border-radius: 100%;
14 | }
15 | & .right-side {
16 | width: 300px;
17 | height: 400px;
18 | position: absolute;
19 | right: 60px;
20 | top: 0;
21 | bottom: 0;
22 | margin: auto;
23 | & * {
24 | pointer-events: none;
25 | }
26 | & path {
27 | stroke: #fff;
28 | stroke-width: 50px;
29 | stroke-linecap: round;
30 | fill: none;
31 | }
32 | }
33 | & .blur {
34 | // filter: blur(2px);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/site/theme/static/page.less:
--------------------------------------------------------------------------------
1 | @import "./custom";
2 | @contentPage: page;
3 | .home .page-wrapper.tween-one-leaving {
4 | margin-top: 64px;
5 | }
6 |
7 | .@{contentPage}-wrapper {
8 | width: 100%;
9 | overflow: hidden;
10 | position: relative;
11 | .@{contentPage}-nav {
12 | background: #fff;
13 | box-shadow: 0 1px 0 #eee;
14 | overflow: hidden;
15 | height: 80px;
16 | position: relative;
17 | & ul {
18 | max-width: 1200px;
19 | padding: 0 24px;
20 | margin: auto;
21 | position: relative;
22 | & li {
23 | float: left;
24 | height: 80px;
25 | text-align: center;
26 | &[disabled] {
27 | cursor: not-allowed;
28 | & * {
29 | pointer-events: none;
30 | color: fade(@nav-link-color, 16);
31 | }
32 | }
33 | & a {
34 | color: #989898;
35 | display: block;
36 | height: 100%;
37 | padding-top: 30px;
38 | font-size: 14px;
39 | border-bottom: 1px solid transparent;
40 | transition: border @animate-duration @ease-out, color @animate-duration @ease-out;
41 | & span {
42 | display: block;
43 | font-size: 12px;
44 | color: @title-color;
45 | transition: color @animate-duration @ease-out;
46 | }
47 | &:hover {
48 | color: #4d4d4d;
49 | border-bottom-color: #4d4d4d;
50 | & span {
51 | color: fade(@nav-link-active-color, 55);
52 | }
53 | }
54 | }
55 | &.active {
56 | & a {
57 | color: #4d4d4d;
58 | border-bottom-color: #4d4d4d;
59 | & span {
60 | color: fade(@nav-link-active-color, 55);
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | .@{contentPage} {
68 | width: 100%;
69 | border-radius: 6px;
70 | max-width: 1200px;
71 | min-height: 800px;
72 | padding: 64px 24px 0;
73 | margin: auto;
74 | position: relative;
75 | & .page-content-wrapper {
76 | padding: 0 0 64px 64px;
77 | border-left: 1px solid @line-color;
78 | }
79 | & .page-content {
80 | position: relative;
81 | }
82 | }
83 | }
84 |
85 | .nav-list {
86 | &-wrapper {
87 | height: 100%;
88 | position: relative;
89 | z-index: 1;
90 | li {
91 | &[disabled] {
92 | cursor: not-allowed;
93 | * {
94 | pointer-events: none;
95 | color: @list-disabled-color;
96 | }
97 | }
98 | a {
99 | display: block;
100 | font-size: 14px;
101 | // color: @text-color;
102 | overflow: hidden;
103 | text-overflow: ellipsis;
104 | transition: color @animate-duration @ease-out;
105 | &:hover {
106 | // color: @primary-color;
107 | }
108 | }
109 | &.active a {
110 | color: @primary-color;
111 | }
112 | }
113 | }
114 | h2 {
115 | font-size: 16px;
116 | margin-bottom: 32px;
117 | position: absolute;
118 | padding-left: 16px;
119 | }
120 | >ul {
121 | top: 48px;
122 | position: absolute;
123 | }
124 | .ant-menu-inline .ant-menu-item,
125 | .ant-menu-inline .ant-menu-submenu-title {
126 | width: ~"calc(100% + 1px)";
127 | }
128 | .ant-menu {
129 | background: transparent;
130 | &.ant-menu-inline {
131 | border-right: none;
132 | }
133 | .ant-menu-item-selected {
134 | background-color: transparent;
135 | }
136 | .ant-menu-item {
137 | line-height: 32px;
138 | height: 32px;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/site/theme/static/splicing.less:
--------------------------------------------------------------------------------
1 | @import "./custom";
2 |
3 | @content: splicing;
4 | .@{content}-wrapper {
5 | & .bottom-btn {
6 | text-align: center;
7 | margin: 20px 0;
8 | }
9 | }
10 |
11 | .@{content} {
12 | & h2 {
13 | font-size: 22px;
14 | font-weight: normal;
15 | & > span {
16 | font-size: 14px;
17 | }
18 | }
19 | &-tag-wrapper {
20 | display: inline-block;
21 | font-size: 14px;
22 | margin-left: 10px;
23 | line-height: 30px;
24 | vertical-align: middle;
25 | & span {
26 | display: inline-block;
27 | }
28 | }
29 | .rc-autoresponsive-container {
30 | margin-top: 20px;
31 | & > .item {
32 | transition: transform .3s @ease-out;
33 | &[disabled] {
34 |
35 | pointer-events: none;
36 | overflow: hidden;
37 | & .disabled-test {
38 | position: absolute;
39 | top: -13px;
40 | left: -38px;
41 | background: @template-text-color;
42 | color: @template-text-color-light;
43 | z-index: 50;
44 | height: 50px;
45 | line-height: 80px;
46 | transform: rotate(-45deg);
47 | width: 100px;
48 | text-align: center;
49 | filter: grayscale(0%);
50 | font-size: 12px;
51 | box-shadow: 0 3px 5px rgba(0, 0, 0, .2);
52 | }
53 | & * {
54 | filter: grayscale(100%);
55 | }
56 | }
57 | & > a {
58 | display: block;
59 | padding: 0 10px;
60 | line-height: 150px;
61 | text-align: center;
62 | font-size: 0;
63 | position: relative;
64 | overflow: hidden;
65 | background: #fff;
66 | .page-pro();
67 | transition: box-shadow .3s @ease-out, transform .3s @ease-out;
68 | & .item-text {
69 | position: absolute;
70 | overflow: hidden;
71 | width: 100%;
72 | bottom: -30px;
73 | margin-left: -10px;
74 | border-radius: 0 0 6px 6px;
75 | background: fade(@primary-color, 65);
76 | line-height: 30px;
77 | font-size: 12px;
78 | color: #fff;
79 | opacity: 0;
80 | transition: opacity .5s @ease-out, bottom .3s @ease-out;
81 | }
82 |
83 | &:hover {
84 | & .item-text {
85 | bottom: 0;
86 | opacity: 1 !important;
87 | }
88 | }
89 | & img {
90 | vertical-align: middle;
91 | }
92 | & .check {
93 | position: absolute;
94 | right: 20px;
95 | top: 20px;
96 | font-size: 24px;
97 | }
98 | }
99 | }
100 | }
101 |
102 | &-modal-title {
103 | font-weight: normal;
104 | }
105 |
106 | &-modal-explain {
107 | text-align: center;
108 | }
109 |
110 | &-modal-img-wrapper {
111 | width: 250px;
112 | margin: 10px auto 20px;
113 | padding: 10px;
114 | border-radius: 6px;
115 | border: 1px solid @line-color;
116 | position: relative;
117 | & span, & img {
118 | display: block;
119 | }
120 | & span {
121 | cursor: move;
122 | cursor: grab;
123 | cursor: -moz-grab;
124 | cursor: -webkit-grab;
125 | &:active {
126 | cursor: grabbing;
127 | cursor: -moz-grabbing;
128 | cursor: -webkit-grabbing;
129 | }
130 | }
131 | & img {
132 | pointer-events: none;
133 | }
134 | }
135 | &-modal-button-wrapper {
136 | text-align: center;
137 | & button:last-child {
138 | margin-left: 10px;
139 | }
140 | }
141 | &-checkbox-wrapper {
142 | margin-top: 20px;
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/site/theme/static/style.js:
--------------------------------------------------------------------------------
1 | import 'antd/lib/button/style';
2 | import 'antd/lib/table/style';
3 | import 'antd/lib/input/style';
4 | import 'antd/lib/input-number/style';
5 | import 'rc-drawer/assets/index.css';
6 | import 'react-github-button/assets/style.css';
7 | import './global.less';
8 | import './common.less';
9 | import './highlight.less';
10 | import './footer.less';
11 | import './home.less';
12 | import './page.less';
13 | import './markdown.less';
14 | import './demolayout.less';
15 | import './demo.less';
16 | import './splicing.less';
17 | import './exhibition.less';
18 | import './logo-demo.less';
19 | import './responsive.less';
20 |
--------------------------------------------------------------------------------
/site/theme/template/Content/Article.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { getChildren } from 'jsonml.js/lib/utils';
3 | import DocumentTitle from 'react-document-title';
4 | import { Alert } from 'antd';
5 | import * as utils from '../utils';
6 |
7 | class Article extends React.PureComponent {
8 | render() {
9 | const { ...props } = this.props;
10 | const { locale } = props.intl;
11 | const pageData = props.pageData;
12 | if (!pageData) {
13 | return (
14 |
15 |
你要找的页面不存在!!!
16 |
返回首页
17 |
18 | );
19 | }
20 | const {
21 | meta, content, toc, api,
22 | } = pageData;
23 | const {
24 | title, subtitle,
25 | } = meta;
26 | const tocItem = props.utils.toReactComponent(toc);
27 | const tocChildren = utils.toArrayChildren(tocItem.props.children).map((item) => {
28 | const itemChildren = utils.toArrayChildren(item.props.children).map((cItem) => React.cloneElement(cItem, {
29 | onClick: utils.scrollClick,
30 | }));
31 | return React.cloneElement(item, item.props, itemChildren);
32 | });
33 | const isNotTranslated = locale === 'en-US' && typeof title === 'object';
34 | const isZhCN = locale === 'zh-CN';
35 | return (
36 |
37 |
38 | {isNotTranslated && (
39 |
43 | This article has not been translated yet. Wan't to help us out?
44 | {' '}
45 |
46 | See this issue on GitHub.
47 |
48 |
49 | )}
50 | style={{ marginBottom: 24 }}
51 | />
52 | )}
53 |
54 | {isZhCN ? subtitle || title['en-US'] || title : subtitle || title[locale] || title}
55 | {isZhCN && {title['zh-CN'] || ''} }
56 |
57 | {!toc || toc.length <= 1 ? null
58 | : (
59 |
60 | {React.cloneElement(tocItem, tocItem.props, tocChildren)}
61 |
62 | )}
63 | {!content ? null
64 | : props.utils.toReactComponent(['section', { className: 'markdown' }]
65 | .concat(getChildren(content)))}
66 | {api ? props.utils.toReactComponent(['section', {
67 | className: 'markdown api-container',
68 | }].concat(getChildren(api))) : null}
69 |
70 |
71 | );
72 | }
73 | }
74 | Article.propTypes = {};
75 |
76 | Article.defaultProps = {};
77 | export default Article;
78 |
--------------------------------------------------------------------------------
/site/theme/template/Content/ComponentDoc.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import ReactDOM from 'react-dom';
4 | import DocumentTitle from 'react-document-title';
5 | import GitHubButton from 'react-github-button';
6 | import { Alert } from 'antd';
7 | import DemoLayout, { Item } from './DemoLayout';
8 |
9 | class ComponentDoc extends React.PureComponent {
10 | componentDidMount() {
11 | const props = this.props;
12 | const { location } = props;
13 | this.hash = location.hash;
14 | if (window.addEventListener) {
15 | window.addEventListener('scroll', this.onScroll);
16 | } else {
17 | window.attachEvent('onscroll', this.onScroll);
18 | }
19 | }
20 |
21 | componentWillUnmount() {
22 | if (window.addEventListener) {
23 | window.removeEventListener('scroll', this.onScroll);
24 | } else {
25 | window.detachEvent('onscroll', this.onScroll);
26 | }
27 | }
28 |
29 | onScroll = () => {
30 | const tops = this.demoIds.map((item) => {
31 | const dom = document.getElementById(item);
32 | let top = dom.getBoundingClientRect().top;
33 | if (top < 0) {
34 | top = -top;
35 | }
36 | return top;
37 | });
38 | const t = Math.min.apply(null, tops);
39 | const id = this.demoIds[tops.indexOf(t)];
40 | const link = `#${id}`;
41 | if (this.hash !== link) {
42 | /* eslint-disable no-restricted-globals */
43 | history.pushState(null, window.title, `#${id}`);
44 | /* eslint-enable no-restricted-globals */
45 | // cWindow.location.hash = `#${id}`;
46 | this.hash = link;
47 | }
48 | };
49 |
50 | render() {
51 | const { ...props } = this.props;
52 | const { pageData, demos } = props;
53 | const { locale } = props.intl;
54 | const isZhCN = locale === 'zh-CN';
55 | if (!pageData) {
56 | return (
57 |
58 |
你要找的页面不存在!!!
59 |
返回首页
60 |
61 | );
62 | }
63 | const demosToChild = Object.keys(demos).map((key) => demos[key])
64 | .filter((item) => !item.meta.hidden)
65 | .sort((a, b) => a.meta.order - b.meta.order)
66 | .map((item, i) => {
67 | const content = props.utils.toReactComponent(['div'].concat(item.content[locale] || item.content));
68 | const comp = item.preview;
69 | return (
70 | -
82 | {comp(React, ReactDOM)}
83 |
84 | );
85 | });
86 | const { meta, description } = pageData;
87 | const {
88 | title, subtitle,
89 | } = meta;
90 | this.demoIds = demosToChild.map((item) => item.props.id);
91 |
92 | const isNotTranslated = locale === 'en-US' && typeof title === 'object';
93 | return (
94 |
95 |
96 | {isNotTranslated && (
97 |
101 | This article has not been translated yet. Wan't to help us out?
102 | {' '}
103 |
104 | See this issue on GitHub.
105 |
106 |
107 | )}
108 | style={{ marginBottom: 24 }}
109 | />
110 | )}
111 |
112 | {isZhCN ? subtitle || title['en-US'] || title : subtitle || title[locale] || title}
113 | {isZhCN && {title['zh-CN'] || ''} }
114 |
120 |
121 | {description ? props.utils.toReactComponent(description) : null}
122 |
123 | {demosToChild}
124 |
125 |
126 |
127 | );
128 | }
129 | }
130 |
131 | ComponentDoc.propTypes = {
132 | params: PropTypes.any,
133 | };
134 |
135 | ComponentDoc.defaultProps = {};
136 | export default ComponentDoc;
137 |
--------------------------------------------------------------------------------
/site/theme/template/Content/DemoItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import ReactDOM from 'react-dom';
4 | import TweenOne from 'rc-tween-one';
5 | import { Icon } from 'antd';
6 |
7 | class Item extends React.PureComponent {
8 | constructor(props) {
9 | super(props);
10 | this.state = {
11 | paused: true,
12 | codeOpen: false,
13 | codeHeight: 0,
14 | styleHeight: 0,
15 | };
16 | }
17 |
18 | componentDidMount() {
19 | this.setDomHeight();
20 | }
21 |
22 | setDomHeight = () => {
23 | const codeDom = ReactDOM.findDOMNode(this.code);
24 | const styleDom = ReactDOM.findDOMNode(this.style);
25 | this.setState({
26 | codeHeight: codeDom.offsetHeight,
27 | styleHeight: styleDom && styleDom.offsetHeight,
28 | });
29 | }
30 |
31 | mouseEnter = () => {
32 | this.setState({
33 | paused: false,
34 | });
35 | }
36 |
37 | mouseLeave = () => {
38 | this.setState({
39 | paused: true,
40 | });
41 | }
42 |
43 | codeSwitch = () => {
44 | this.setState({
45 | codeOpen: !this.state.codeOpen,
46 | });
47 | }
48 |
49 | render() {
50 | let children = this.props.children;
51 | if (typeof children === 'object') {
52 | const childProps = { ...this.props.children.props };
53 | if (this.props.mouseEnter) {
54 | childProps.paused = this.state.paused;
55 | }
56 | children = React.cloneElement(this.props.children, childProps);
57 | }
58 | const animate = this.state.codeHeight && this.state.codeOpen ? {
59 | height: this.state.codeHeight, duration: 300,
60 | } : (this.state.codeHeight && { height: 220, duration: 300 }) || {};
61 | const styleAnimate = this.state.styleHeight && this.state.codeOpen ? {
62 | height: this.state.styleHeight, duration: 300,
63 | } : (this.state.styleHeight && { height: 220, duration: 300 }) || {};
64 | const iconAnimate = this.state.codeHeight && this.state.codeOpen ? {
65 | rotate: 180, y: -2, duration: 300,
66 | } : (this.state.codeHeight && { rotate: 0, y: 0, duration: 300 }) || {};
67 | return (
68 |
72 | {this.props.title}
73 | {this.props.content}
74 |
75 |
82 | {children}
83 | {this.props.cStyle
84 | ? : null}
85 |
86 |
87 |
{ this.code = c; }}
91 | animation={this.state.codeHeight > 220 ? animate : null}
92 | >
93 | {this.props.code}
94 |
95 | {this.props.styleCode
96 | ? (
97 |
{ this.style = c; }}
101 | animation={styleAnimate}
102 | >
103 |
104 |
105 |
106 |
107 | )
108 | : null}
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | );
118 | }
119 | }
120 |
121 | Item.propTypes = {
122 | children: PropTypes.any,
123 | className: PropTypes.string,
124 | title: PropTypes.any,
125 | content: PropTypes.any,
126 | vertical: PropTypes.bool,
127 | styleCode: PropTypes.string,
128 | cStyle: PropTypes.string,
129 | mouseEnter: PropTypes.bool,
130 | id: PropTypes.string,
131 | code: PropTypes.any,
132 | };
133 |
134 | Item.defaultProps = {
135 | className: 'code-box',
136 | };
137 | export default Item;
138 |
--------------------------------------------------------------------------------
/site/theme/template/Content/DemoLayout.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import Item from './DemoItem';
4 |
5 | class DemoLayout extends React.PureComponent {
6 | renderChildren = () => React.Children.map(this.props.children, (item) => {
7 | if (item.type === Item) {
8 | const vertical = item.props.vertical;
9 | if (typeof vertical === 'boolean') {
10 | return item;
11 | }
12 | return React.cloneElement(item, { vertical: this.props.vertical });
13 | }
14 | return null;
15 | });
16 |
17 | render() {
18 | const props = { ...this.props };
19 | delete props.vertical;
20 | return (
21 |
22 |
23 | {this.renderChildren()}
24 |
25 |
26 | );
27 | }
28 | }
29 |
30 | DemoLayout.propTypes = {
31 | children: PropTypes.any,
32 | className: PropTypes.string,
33 | vertical: PropTypes.bool,
34 | };
35 | DemoLayout.defaultProps = {
36 | className: 'demo-layout',
37 | };
38 | // DemoLayout.Item = Item;
39 |
40 | export default DemoLayout;
41 |
42 | export {
43 | Item,
44 | };
45 |
--------------------------------------------------------------------------------
/site/theme/template/Exhibition/Details.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import PropTypes from 'prop-types';
4 | import TweenOne from 'rc-tween-one';
5 | import { FormattedMessage, injectIntl } from 'react-intl';
6 | import DocumentTitle from 'react-document-title';
7 |
8 | class Details extends React.Component {
9 | static propTypes = {
10 | className: PropTypes.string,
11 | pageData: PropTypes.object,
12 | };
13 |
14 | static defaultProps = {
15 | className: 'exhibition-details',
16 | };
17 |
18 | constructor(props) {
19 | super(props);
20 | this.state = {
21 | replay: false,
22 | };
23 | }
24 |
25 | shouldComponentUpdate() {
26 | return this.state.replay;
27 | }
28 |
29 | onClick = () => {
30 | this.setState({
31 | replay: true,
32 | }, () => {
33 | this.setState({
34 | replay: false,
35 | });
36 | });
37 | };
38 |
39 | render() {
40 | const { ...props } = this.props;
41 | const { params, intl } = props;
42 | const { locale } = intl;
43 | const pageData = this.props.localizedPageData[params.children.replace('-cn', '')];
44 | const className = this.props.className;
45 | const {
46 | meta, content, highlightedStyle,
47 | style, preview, highlightedCode,
48 | } = pageData;
49 | const {
50 | title, subtitle,
51 | } = meta;
52 | return (
53 |
54 |
55 |
56 |
57 |
58 | {!this.state.replay && preview(React, ReactDOM)}
59 |
60 |
61 |
62 |
63 |
64 | {subtitle || title[locale]}
65 |
66 | {props.utils.toReactComponent(['section'].concat(meta.content[locale]))}
67 | {!!content[locale].length && props.utils.toReactComponent(['section'].concat(content[locale]))}
68 |
69 | {!!style && }
70 | jsx
71 | {!!highlightedCode.length && props.utils.toReactComponent(highlightedCode)}
72 | {highlightedStyle && css }
73 | {highlightedStyle && (
74 |
75 |
76 |
77 | )}
78 |
79 |
80 |
81 |
82 | );
83 | }
84 | }
85 |
86 | export default injectIntl(Details);
87 |
--------------------------------------------------------------------------------
/site/theme/template/Exhibition/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import TweenOne from 'rc-tween-one';
4 | import DocumentTitle from 'react-document-title';
5 | import { injectIntl } from 'react-intl';
6 | import { Link } from 'react-router';
7 | import * as utils from '../utils';
8 |
9 | class Exhibition extends React.Component {
10 | static propTypes = {
11 | className: PropTypes.string,
12 | localizedPageData: PropTypes.object,
13 | };
14 |
15 | static defaultProps = {
16 | className: 'exhibition-list',
17 | };
18 |
19 | render() {
20 | const { locale } = this.props.intl;
21 | const demo = this.props.localizedPageData;
22 | const listChildren = Object.keys(demo).map((key) => demo[key])
23 | .sort((a, b) => b.meta.order - a.meta.order)
24 | .map((item) => {
25 | const img = item.meta.image;
26 | const link = utils.getLocalizedPathname(item.meta.filename.replace(/(\/index)|(.md)/g, ''), locale === 'zh-CN');
27 | const title = item.meta.title[locale];
28 | return (
29 |
30 |
31 |
32 |
33 | {title}
34 |
35 | );
36 | });
37 | return (
38 |
39 |
40 |
45 | {listChildren}
46 |
47 |
48 |
49 |
50 | );
51 | }
52 | }
53 |
54 | export default injectIntl(Exhibition);
55 |
--------------------------------------------------------------------------------
/site/theme/template/Home/Banner.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import TweenOne from 'rc-tween-one';
4 | import QueueAnim from 'rc-queue-anim';
5 | import ScrollElement from 'rc-scroll-anim/lib/ScrollElement';
6 | import SvgMorphPlugin from 'rc-tween-one/lib/plugin/SvgMorphPlugin';
7 | import { FormattedMessage } from 'react-intl';
8 | import { Link } from 'react-router';
9 | import { Icon } from 'antd';
10 | import Demo from './Demo';
11 | import * as utils from '../utils';
12 |
13 | TweenOne.plugins.push(SvgMorphPlugin);
14 |
15 | export default class Banner extends React.PureComponent {
16 | static propTypes = {
17 | className: PropTypes.string,
18 | };
19 |
20 | static defaultProps = {
21 | className: 'banner',
22 | };
23 |
24 | render() {
25 | const { isZhCN } = this.props;
26 | return (
27 |
28 |
29 |
39 |
49 |
50 |
51 |
52 |
53 |
54 |
59 | Motion Design
60 | Animation specification and components of Ant Design.
61 |
62 |
63 |
64 |
65 |
66 |
83 |
84 |
88 |
89 |
93 |
94 |
95 |
96 |
100 |
106 |
107 |
108 |
109 |
110 | );
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/site/theme/template/Home/CodeDemo.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDom from 'react-dom';
3 | import PropTypes from 'prop-types';
4 | import { Icon } from 'antd';
5 | import { enquireScreen } from 'enquire-js';
6 |
7 | class CodeDemo extends React.PureComponent {
8 | static propTypes = {
9 | className: PropTypes.string,
10 | pageData: PropTypes.object,
11 | utils: PropTypes.any,
12 | };
13 |
14 | static defaultProps = {
15 | className: 'code',
16 | };
17 |
18 | constructor(props) {
19 | super(props);
20 | const queueAnimDemo = props.pageData['queue-anim'];
21 | this.state = {
22 | code: props.utils
23 | .toReactComponent(queueAnimDemo.simple.highlightedCode),
24 | component: queueAnimDemo.simple.preview(React, ReactDom),
25 | replay: false,
26 | isMobile: false,
27 | openCode: false,
28 | };
29 | }
30 |
31 | componentDidMount() {
32 | enquireScreen((bool) => {
33 | const isMobile = bool;
34 | this.setState({ isMobile });
35 | });
36 | }
37 |
38 | onClick = () => {
39 | this.setState({
40 | replay: true,
41 | }, () => {
42 | this.setState({
43 | replay: false,
44 | });
45 | });
46 | };
47 |
48 | codeClick = () => {
49 | this.setState({
50 | openCode: true,
51 | });
52 | };
53 |
54 | codeCloseClick = () => {
55 | this.setState({
56 | openCode: false,
57 | });
58 | };
59 |
60 | render() {
61 | return (
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | {this.state.code}
70 |
71 |
72 |
73 |
74 |
75 |
76 | {this.state.isMobile && (
77 |
78 |
79 |
80 | )}
81 |
82 |
83 | {this.state.replay ? null : this.state.component}
84 |
85 |
86 |
87 |
88 | {
89 | this.state.isMobile && (
90 |
91 |
92 |
93 | )
94 | }
95 |
96 | );
97 | }
98 | }
99 |
100 | export default CodeDemo;
101 |
--------------------------------------------------------------------------------
/site/theme/template/Home/Page1.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
4 | import QueueAnim from 'rc-queue-anim';
5 | import TweenOne from 'rc-tween-one';
6 | import { Link } from 'react-router';
7 | import { FormattedMessage } from 'react-intl';
8 | import CoderDemo from './CodeDemo';
9 | import * as utils from '../utils';
10 |
11 | export default class Page1 extends React.PureComponent {
12 | static propTypes = {
13 | pageData: PropTypes.object,
14 | utils: PropTypes.object,
15 | tweenAnim: PropTypes.object,
16 | onButtonClick: PropTypes.func,
17 | };
18 |
19 | static defaultProps = {
20 | pageData: {},
21 | utils: {},
22 | tweenAnim: {},
23 | onButtonClick: () => {
24 | },
25 | };
26 |
27 | render() {
28 | const { isZhCN } = this.props;
29 | return (
30 |
31 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
47 |
48 |
49 |
54 |
58 |
59 |
60 |
61 |
62 |
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/site/theme/template/Home/Page2.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { FormattedMessage, injectIntl } from 'react-intl';
4 | import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
5 | import QueueAnim from 'rc-queue-anim';
6 | import TweenOne from 'rc-tween-one';
7 |
8 | import { Link } from 'react-router';
9 |
10 | import * as utils from '../utils';
11 |
12 | class Page2 extends React.PureComponent {
13 | static propTypes = {
14 | pageData: PropTypes.object,
15 | utils: PropTypes.object,
16 | tweenAnim: PropTypes.object,
17 | onButtonClick: PropTypes.func,
18 | };
19 |
20 | static defaultProps = {
21 | pageData: {},
22 | utils: {},
23 | tweenAnim: {},
24 | onButtonClick: () => {
25 | },
26 | };
27 |
28 |
29 | render() {
30 | const { locale } = this.props.intl;
31 | const isZhCN = locale === 'zh-CN';
32 | const exhibition = this.props.pageData.exhibition;
33 | const demoToChildren = Object.keys(exhibition)
34 | .map((key) => exhibition[key])
35 | .sort((a, b) => b.meta.order - a.meta.order)
36 | .filter((key, i) => i < 6)
37 | .map((item) => {
38 | const img = item.meta.image;
39 | const link = item.meta.filename.replace(/(\/index)|(.md)/g, '');
40 | const title = item.meta.title[locale] || item.meta.chinese || item.meta.english;
41 | const content = this.props.utils.toReactComponent(item.meta.content[locale]);
42 | return (
43 |
44 |
45 |
46 | {title}
47 | {content}
48 |
49 |
50 | );
51 | });
52 |
53 | return (
54 |
55 |
60 |
67 |
68 |
69 |
70 |
71 |
72 |
77 |
78 | {demoToChildren}
79 |
80 |
81 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | );
93 | }
94 | }
95 |
96 | export default injectIntl(Page2);
97 |
--------------------------------------------------------------------------------
/site/theme/template/Home/Page3.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import OverPack from 'rc-scroll-anim/lib/ScrollOverPack';
4 | import QueueAnim from 'rc-queue-anim';
5 | import { FormattedMessage } from 'react-intl';
6 | import { Link } from 'react-router';
7 | import * as utils from '../utils';
8 |
9 | export default class Page3 extends React.PureComponent {
10 | static propTypes = {
11 | onButtonClick: PropTypes.func,
12 | };
13 |
14 | static defaultProps = {
15 | onButtonClick: () => {
16 | },
17 | };
18 |
19 | render() {
20 | const { isZhCN } = this.props;
21 | return (
22 |
23 |
28 |
34 |
35 |
36 |
37 |
38 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/site/theme/template/Home/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import DocumentTitle from 'react-document-title';
4 | import ScrollLink from 'rc-scroll-anim/lib/ScrollLink';
5 | import * as utils from '../utils';
6 |
7 | import Banner from './Banner';
8 | import Page1 from './Page1';
9 | import Page2 from './Page2';
10 | import Page3 from './Page3';
11 |
12 |
13 | class Home extends React.PureComponent {
14 | static propTypes = {
15 | localizedPageData: PropTypes.object,
16 | utils: PropTypes.object,
17 | };
18 |
19 | constructor(props) {
20 | super(props);
21 | this.tweenAnim = {
22 | y: 30, opacity: 0, type: 'from', ease: 'easeOutQuad',
23 | };
24 | }
25 |
26 | scrollToTop = () => {
27 | utils.scrollTo(0);
28 | };
29 |
30 | render() {
31 | const { pathname } = this.props.location;
32 | const isZhCN = utils.isZhCN(pathname);
33 | return (
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
50 |
56 |
57 |
58 |
59 | );
60 | }
61 | }
62 |
63 | export default Home;
64 |
--------------------------------------------------------------------------------
/site/theme/template/Layout/Layout.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import ReactDOM from 'react-dom';
4 | import { IntlProvider } from 'react-intl';
5 | import { ConfigProvider } from 'antd';
6 | import zhCN from 'antd/es/locale/zh_CN';
7 | import TweenOne from 'rc-tween-one';
8 | import { enquireScreen } from 'enquire-js';
9 | import Header from './Header';
10 | import Footer from './Footer';
11 | import Page from '../Content/Page';
12 | import '../../static/style';
13 |
14 | import enLocale from '../../en-US';
15 | import cnLocale from '../../zh-CN';
16 | import * as utils from '../utils';
17 |
18 | if (typeof window !== 'undefined') {
19 | /* eslint-disable global-require */
20 | require('../../static/style');
21 |
22 | // Expose to iframe
23 | window.react = React;
24 | window['react-dom'] = ReactDOM;
25 | window.antd = require('antd');
26 | /* eslint-enable global-require */
27 | }
28 |
29 | let isMobile = false;
30 | enquireScreen((b) => {
31 | isMobile = b;
32 | });
33 |
34 | class Layout extends React.PureComponent {
35 | static propTypes = {
36 | children: PropTypes.any,
37 | location: PropTypes.object,
38 | localizedPageData: PropTypes.any,
39 | };
40 |
41 | static childContextTypes = {
42 | isMobile: PropTypes.bool,
43 | };
44 |
45 | constructor(props) {
46 | super(props);
47 | const { pathname } = props.location;
48 | const appLocale = utils.isZhCN(pathname) ? cnLocale : enLocale;
49 |
50 | this.state = {
51 | appLocale,
52 | isMobile,
53 | };
54 | }
55 |
56 | getChildContext() {
57 | const { isMobile: mobile } = this.state;
58 | return { isMobile: mobile };
59 | }
60 |
61 | componentDidMount() {
62 | enquireScreen((b) => {
63 | this.setState({
64 | isMobile: !!b,
65 | });
66 | });
67 | }
68 |
69 | onChange = (e) => {
70 | // fixed 与 transform
71 | if (e.type === 'enter') {
72 | const dom = ReactDOM.findDOMNode(this.content);
73 | Array.prototype.slice.call(dom.children).forEach((item) => {
74 | const cItem = item;
75 | cItem.style.transform = 'none';
76 | });
77 | }
78 | }
79 |
80 | render() {
81 | const { location, children, localizedPageData } = this.props;
82 | const { pathname, hash } = location;
83 | const { appLocale } = this.state;
84 | const pathKey = pathname && pathname.split('/')[0].replace('-cn', '');
85 | const key = !pathKey || pathKey === 'index' ? 'index' : 'page';
86 | const childrenToRender = key === 'index' || pathKey === 'exhibition'
87 | ? React.cloneElement(this.props.children, {
88 | key: pathKey ? pathname : key,
89 | localizedPageData,
90 | isMobile: this.state.isMobile,
91 | })
92 | : (
93 |
101 | {children}
102 |
103 | );
104 | return (
105 |
106 |
107 |
108 |
109 | { this.content = c; }}
115 | >
116 | {
117 | childrenToRender
118 | }
119 |
120 |
121 |
122 |
123 |
124 | );
125 | }
126 | }
127 |
128 | export default Layout;
129 |
--------------------------------------------------------------------------------
/site/theme/template/Layout/index.jsx:
--------------------------------------------------------------------------------
1 | import collect from 'bisheng/collect';
2 | import Layout from './Layout';
3 | import * as utils from '../utils';
4 |
5 | export default collect(async (nextProps) => {
6 | const pathname = nextProps.location.pathname;
7 |
8 | const path = pathname.replace('-cn', '');
9 |
10 | let pageDataPath = path.split('/');
11 |
12 | if (path === 'index' || path === '/') {
13 | // exhibition.demo, queue-anim.simple.demo
14 | const exhibitionPageData = nextProps.utils.get(nextProps.data, ['exhibition']).demo();
15 | const componentsPageData = nextProps.utils.get(nextProps.data, ['components'])['queue-anim'].demo();
16 | return {
17 | localizedPageData: {
18 | exhibition: await exhibitionPageData,
19 | 'queue-anim': await componentsPageData,
20 | },
21 | };
22 | }
23 | if (/\/components/.test(path) && pageDataPath[1]) {
24 | const str = pageDataPath[1];
25 | pageDataPath[1] = str.charAt(0).toUpperCase() + str.slice(1);
26 | }
27 |
28 | if (/exhibition/.test(path) && pageDataPath[1]) {
29 | pageDataPath = pageDataPath.slice(0, pageDataPath.length - 1);
30 | }
31 |
32 | if (/api/.test(path) && pageDataPath[1]) {
33 | pageDataPath = ['components', pageDataPath[1]];
34 | }
35 | let pageData = nextProps.utils.get(nextProps.data, pageDataPath);
36 | pageData = pageDataPath[0] === 'exhibition' && !pageDataPath[1] ? pageData.demo : pageData;
37 |
38 | // 路由跳转统一处理
39 | if (pathname === 'components') {
40 | location.href = '/components/tween-one';
41 | return;
42 | }
43 |
44 | if (!pageData) {
45 | throw 404; // eslint-disable-line no-throw-literal
46 | }
47 | const locale = utils.isZhCN(pathname) ? 'zh-CN' : 'en-US';
48 | const pageDataPromise = typeof pageData === 'function'
49 | ? pageData() : (pageData[locale] || pageData.index[locale] || pageData.index)();
50 | const demosFetcher = nextProps.utils.get(nextProps.data, [...pageDataPath, 'demo']);
51 | if (demosFetcher) {
52 | const [localizedPageData, demos] = await Promise.all([pageDataPromise, demosFetcher()]);
53 | return { localizedPageData, demos };
54 | }
55 | return { localizedPageData: await pageDataPromise };
56 | })(Layout);
57 |
--------------------------------------------------------------------------------
/site/theme/template/Layout/nav.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by jljsj on 16/8/18.
3 | */
4 | import React from 'react';
5 | import { FormattedMessage } from 'react-intl';
6 |
7 | export default [
8 | { name: , href: '/exhibition/', key: 'exhibition' },
9 | { name: , href: '/language/basic', key: 'language' },
10 | { name: , href: '/components/tween-one', key: 'components' },
11 | { name: 'API', href: '/api/tween-one', key: 'api' },
12 | {
13 | name: ,
14 | href: 'https://landing.ant.design',
15 | key: 'template',
16 | open: true,
17 | },
18 | ];
19 |
--------------------------------------------------------------------------------
/site/theme/template/NotFound.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Link } from 'react-router';
4 |
5 | export default function NotFound(props) {
6 | return (
7 |
8 |
9 | 404
10 |
11 | 你要找的页面不存在
12 | 返回首页
13 |
14 |
15 |
20 |
21 | );
22 | }
23 |
24 | NotFound.propTypes = {
25 | className: PropTypes.string,
26 | };
27 |
--------------------------------------------------------------------------------
/site/theme/template/other/EaseExplain.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import TweenOne from 'rc-tween-one';
4 |
5 | class EaseExplain extends React.Component {
6 | static propTypes = {
7 | className: PropTypes.string,
8 | leftHide: PropTypes.bool,
9 | rightHide: PropTypes.bool,
10 | title: PropTypes.string,
11 | circleStyle: PropTypes.object,
12 | animation: PropTypes.object,
13 | children: PropTypes.any,
14 | };
15 |
16 | static defaultProps = {
17 | className: 'content',
18 | };
19 |
20 | constructor(props) {
21 | super(props);
22 | this.state = {
23 | animation: this.props.animation,
24 | circleStyle: this.props.circleStyle,
25 | paused: true,
26 | };
27 | }
28 |
29 | mouseOver = () => {
30 | const paused = false;
31 | this.setState({
32 | paused,
33 | });
34 | }
35 |
36 | mouseOut = () => {
37 | const paused = true;
38 | this.setState({
39 | paused,
40 | });
41 | }
42 |
43 | render() {
44 | const lineWidth = 40 * (((this.props.leftHide && 1) || 0) + ((this.props.rightHide && 1) || 0));
45 | return (
46 |
47 |
{this.props.title}
48 |
55 |
56 | {this.props.leftHide ? null :
}
57 |
63 |
64 |
71 |
72 |
73 | {this.props.rightHide ? null :
}
74 |
75 |
76 | {this.props.children}
77 |
78 |
79 |
80 | );
81 | }
82 | }
83 | export default EaseExplain;
84 |
--------------------------------------------------------------------------------
/site/theme/template/other/Principle.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Row, Col } from 'antd/lib/grid';
3 | import './principle.less';
4 |
5 | const text = [
6 | {
7 | title: '自然',
8 | titleEn: 'Natural',
9 | img: 'https://gw.alipayobjects.com/zos/rmsportal/LyTPSGknLUlxiVdwMWyu.gif',
10 | content: '自然运动规律,保证视觉连贯,让用户感知到动作是自然的',
11 | contentEn: 'The animation should based on law of nature. This assures the animation is smooth by its nature and intuitive to its users.',
12 | },
13 | {
14 | title: '高效',
15 | titleEn: 'Efficient',
16 | img: 'https://gw.alipayobjects.com/zos/rmsportal/SQOZVQVIossbXpzDmihu.gif',
17 | content: '尽量节省过渡的时间,快速完成过渡的动画效果',
18 | contentEn: 'The animation should have a transition time as minimal as possible so that it serves its purpose in the most effective way.',
19 | },
20 | {
21 | title: '克制',
22 | titleEn: 'Restrain',
23 | img: 'https://gw.alipayobjects.com/zos/rmsportal/OkIXkscKxywYLSrilPIf.gif',
24 | content: '做有意义的动效,不去做太多的修饰而干扰用户',
25 | contentEn: 'The animation should be meaningful and justified. An over fancy animation will frustrate its users, and therefore should always be avoided.',
26 | },
27 | ];
28 |
29 | export default class Principle extends React.Component {
30 | render() {
31 | const { locale } = this.props;
32 | const isEnUs = locale === 'en-US';
33 | const childrenToRender = text.map((item) => (
34 |
35 |
36 |
37 |
{item[isEnUs ? 'titleEn' : 'title']}
38 |
{item[isEnUs ? 'contentEn' : 'content']}
39 |
40 |
41 | ));
42 | return (
43 |
44 | {childrenToRender}
45 |
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/site/theme/template/other/QueueDemo.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import QueueAnim from 'rc-queue-anim';
3 | import './queueDemo.less';
4 |
5 | class Demo extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | queueShow: false,
10 | };
11 | }
12 |
13 | mouseOverQueue = () => {
14 | this.setState({
15 | queueShow: true,
16 | });
17 | }
18 |
19 | mouseOutQueue = () => {
20 | this.setState({
21 | queueShow: false,
22 | });
23 | }
24 |
25 | render() {
26 | const child = [
27 | ,
28 | ,
29 | ,
30 | ,
31 | ];
32 | return (
33 |
34 |
4.区块出场栅格
35 |
36 |
37 |
38 |
39 |
40 | 以屏幕的对角线为轴,将页面的栅格体系45°旋转,形成出场栅格体系,
41 | 同一栅格体系里的组件和内容的出场时间和效果相同。如果单位刚好居中则更具页面内容和区块划分。
42 |
43 |
示例 demo: (鼠标移到或手指按住以下灰色区域出来效果)
44 |
51 |
52 |
53 |
61 | {this.state.queueShow ? child : null}
62 |
63 |
64 |
65 |
73 | {this.state.queueShow ? child : null}
74 |
75 |
76 |
77 |
85 | {this.state.queueShow ? child : null }
86 |
87 |
88 |
89 |
90 |
91 |
92 | );
93 | }
94 | }
95 | export default Demo;
96 |
--------------------------------------------------------------------------------
/site/theme/template/other/principle.less:
--------------------------------------------------------------------------------
1 | @import "../../static/custom";
2 |
3 | .principle-wrapper {
4 | width: 100%;
5 | .principle {
6 | width: 100%;
7 | min-height: 180px;
8 | display: inline-block;
9 | margin-right: 12.5%;
10 | padding: 24px;
11 | text-align: center;
12 | font-size: 24px;
13 | border-radius: 4px;
14 | border: 1px solid @line-color;
15 | margin-bottom: 24px;
16 | &:last-child {
17 | margin-right: 0;
18 | }
19 | h4 {
20 | margin: 16px 0 8px;
21 | }
22 | p {
23 | font-size: 12px;
24 | line-height: 24px;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/site/theme/template/other/queueDemo.less:
--------------------------------------------------------------------------------
1 | @import "../../static/custom";
2 | .timer-queue-wrapper {
3 | width: 100%;
4 | height: 240px;
5 | margin: 20px auto 0;
6 | background: #f4f4f4;
7 | border-radius: 6px;
8 | overflow: hidden;
9 | & .demo-content {
10 | width: 80%;
11 | margin: 10px auto;
12 | position: relative;
13 | & .demo-kp {
14 | margin: 20px auto;
15 | & > ul > li {
16 | display: inline-block;
17 | width: 22%;
18 | height: 50px;
19 | background: @primary-color;
20 | margin-right: 4%;
21 | &:last-child {
22 | margin-right: 0;
23 | }
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/site/theme/template/template.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | nav: {
3 | name: '导航选择',
4 | order: 0,
5 | data: [
6 | {
7 | src: 'https://zos.alipayobjects.com/rmsportal/ZjfIAdkDVlpnilf.jpg',
8 | text: '普通型',
9 | },
10 | {
11 | src: 'https://zos.alipayobjects.com/rmsportal/UTHsfGMNXXbpEoL.jpg',
12 | text: '带用户型',
13 | },
14 | ],
15 | },
16 | banner: {
17 | name: 'Banner选择',
18 | checkbox: true,
19 | order: 1,
20 | data: [
21 | {
22 | src: 'https://zos.alipayobjects.com/rmsportal/gyseCGEPqWjQpYF.jpg',
23 | text: '单张背景图的主页首屏幕,由一张单屏背景图',
24 | },
25 | {
26 | src: 'https://zos.alipayobjects.com/rmsportal/chnhazooyzrjWSv.jpg',
27 | text: '多张需要显示的背景图的产品主页的首屏',
28 | },
29 | ],
30 | },
31 | content: {
32 | name: '内容选择',
33 | checkbox: true,
34 | order: 2,
35 | data: [
36 | {
37 | src: 'https://zos.alipayobjects.com/rmsportal/CXrFvvZqkMwMHZo.jpg',
38 | text: '产品的特性介绍模块(图左)',
39 | },
40 | {
41 | src: 'https://zos.alipayobjects.com/rmsportal/WxCxyIKjMdCUUSJ.jpg',
42 | text: '产品的特性介绍模块(图右)',
43 | },
44 | {
45 | src: 'https://zos.alipayobjects.com/rmsportal/pUFfIJXizTljrgZ.jpg',
46 | text: '产品有多个功能点介绍的场景',
47 | },
48 | {
49 | src: 'https://zos.alipayobjects.com/rmsportal/ndmJrWwkQloTtKg.jpg',
50 | text: '用于需要video来更好的阐述功能如何使用时',
51 | },
52 | {
53 | src: 'https://zos.alipayobjects.com/rmsportal/sgTBpfjKcsXWDtq.jpg',
54 | text: '案例较多的案例介绍页面',
55 | },
56 | {
57 | src: 'https://zos.alipayobjects.com/rmsportal/yNbeUIWcDNZFKTY.jpg',
58 | text: '产品的一个功能模块有多个特性介绍点',
59 | },
60 | {
61 | src: 'https://zos.alipayobjects.com/rmsportal/CfSeDOXHJzJuPbz.jpg',
62 | text: '产品的多个功能模块特性介绍',
63 | },
64 | { disabled: true, src: 'https://zos.alipayobjects.com/rmsportal/MnbozfSRmOwdxvH.jpg' },
65 | { disabled: true, src: 'https://zos.alipayobjects.com/rmsportal/cMigmCVGBaJkuYG.jpg' },
66 | { disabled: true, src: 'https://zos.alipayobjects.com/rmsportal/VKeYAOSRQVtMccj.jpg' },
67 | { disabled: true, src: 'https://zos.alipayobjects.com/rmsportal/TAvpiZHalFQVewZ.jpg' },
68 | ],
69 | },
70 | footer: {
71 | name: '页尾选择',
72 | order: 3,
73 | data: [
74 | {
75 | src: 'https://zos.alipayobjects.com/rmsportal/aJutnIvTFWkEAWj.jpg',
76 | text: '简单型页尾',
77 | },
78 | {
79 | src: 'https://zos.alipayobjects.com/rmsportal/PEXAhbheOHVTyfM.jpg',
80 | text: '带信息或链接的尾页',
81 | },
82 | ],
83 | },
84 | other: {
85 | name: '其它功能选择',
86 | order: 4,
87 | other: true,
88 | data: [
89 | { label: '悬浮导航', value: 'fixed' },
90 | { label: '侧边小点(页面里的分屏锚点滚动)', value: 'point' },
91 | { label: '整屏滚动', value: 'full' },
92 | ],
93 | },
94 | };
95 |
--------------------------------------------------------------------------------
/site/theme/template/utils.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ticker from 'rc-tween-one/lib/ticker';
3 | import easingTypes from 'tween-functions';
4 |
5 | export function toArrayChildren(children) {
6 | const ret = [];
7 | React.Children.forEach(children, (c) => {
8 | ret.push(c);
9 | });
10 | return ret;
11 | }
12 |
13 | export function currentScrollTop() {
14 | return window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
15 | }
16 |
17 | export function scrollTo(number) {
18 | const scrollTop = currentScrollTop();
19 | if (scrollTop !== number) {
20 | const tickerId = `scrollToTop-${Date.now()}`;
21 | const startFrame = ticker.frame;
22 | ticker.wake(tickerId, () => {
23 | const moment = (ticker.frame - startFrame) * ticker.perFrame;
24 | const ratio = easingTypes.easeInOutCubic(moment, scrollTop, number, 450);
25 | window.scrollTo(window.scrollX, ratio);
26 | if (moment >= 450) {
27 | ticker.clear(tickerId);
28 | }
29 | });
30 | }
31 | }
32 |
33 | export function scrollClick(e) {
34 | const id = e.currentTarget.getAttribute('href').split('#')[1];
35 | const element = document.getElementById(id);
36 | let toTop;
37 | if (element) {
38 | toTop = element.getBoundingClientRect().top;
39 | const docTop = document.documentElement.getBoundingClientRect().top;
40 | toTop = Math.round(toTop) - Math.round(docTop);
41 | scrollTo(toTop);
42 | }
43 | }
44 |
45 | const themeConfig = {
46 | categoryOrder: {
47 | 设计原则: 0,
48 | 动效参数: 5,
49 | 'TweenOne param': 5,
50 | },
51 | };
52 |
53 | export function getMenuItems(moduleData, locale) {
54 | const menuMeta = moduleData.map((item) => item.meta);
55 | const menuItems = [];
56 | const sortFn = (a, b) => (a.order || 0) - (b.order || 0);
57 | menuMeta.sort(sortFn).forEach((meta) => {
58 | if (!meta.category) {
59 | menuItems.push(meta);
60 | } else {
61 | const category = meta.category[locale] || meta.category;
62 | let group = menuItems.filter((i) => i.title === category)[0];
63 | if (!group) {
64 | group = {
65 | type: 'category',
66 | title: category,
67 | children: [],
68 | order: themeConfig.categoryOrder[category],
69 | };
70 | menuItems.push(group);
71 | }
72 | group.children.push(meta);
73 | }
74 | });
75 | return menuItems.map((i) => {
76 | const item = i;
77 | if (item.children) {
78 | item.children = item.children.sort(sortFn);
79 | }
80 | return item;
81 | }).sort(sortFn);
82 | }
83 | export function isZhCN(pathname) {
84 | return /-cn\/?$/.test(pathname);
85 | }
86 |
87 | export function isLocalStorageNameSupported() {
88 | const testKey = 'test';
89 | const storage = window.localStorage;
90 | try {
91 | storage.setItem(testKey, '1');
92 | storage.removeItem(testKey);
93 | return true;
94 | } catch (error) {
95 | return false;
96 | }
97 | }
98 |
99 | export function getLocalizedPathname(path, zhCN) {
100 | const pathname = path.startsWith('/') ? path : `/${path}`;
101 | if (!zhCN) { // to enUS
102 | if (/^\/?index-cn/.test(pathname)) {
103 | return '/';
104 | }
105 | return /\/?index-cn/.test(pathname) ? pathname.replace('/index-cn', '') : pathname.replace('-cn', '');
106 | } if (pathname === '/') {
107 | return '/index-cn';
108 | } if (pathname.endsWith('/')) {
109 | return pathname.replace(/\/$/, '-cn/');
110 | }
111 | return `${pathname}-cn`;
112 | }
113 |
--------------------------------------------------------------------------------
/site/theme/zh-CN.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | locale: 'zh-CN',
4 | messages: {
5 | 'app.header.menu.exhibition': '动效展示',
6 | 'app.header.menu.language': '动效原则',
7 | 'app.header.menu.components': '动效组件',
8 | 'app.header.menu.templates': '动效模板',
9 | 'app.header.lang': 'English',
10 | 'app.home.introduce': '使用 Ant Motion 能够快速在 React 框架中使用动画。',
11 | 'app.home.introduce2': '我们提供了单项,组合动画,以及整套解决方案。',
12 | 'app.home.learn-more': '了解更多',
13 | 'app.home.enter-editor': '快速搭建',
14 | 'app.home.page1.title': 'Ant Motion 让动效更简单',
15 | 'app.home.page1.content': '在 React 框架下,只需要一段简单的代码就可以实现动画效果,可以更好的提高你的工作效率。',
16 | 'app.home.page2.content': '通过 Ant Motion ,可以快速的实现不同组合的动画效果。\n 配合不同交互模式,可以直接运用到你的项目当中。',
17 | 'app.home.page2.learn-more': '更多动画',
18 | 'app.home.page3.title': '为产品添加有趣的动效',
19 | 'app.home.page3.content': '通过更友好的交互方式,让动效穿梭在不同的元素之间,\n 让产品能够更好的和用户对话。',
20 | 'app.home.page3.button': '快速上手',
21 | 'app.details.code': '代码片段',
22 | 'app.content.edit-page': '在 Github 上编辑此页!',
23 | 'app.content.components-exp': '范例',
24 | 'app.footer.repo': '源码仓库',
25 | 'app.footer.template': '模板仓库',
26 | 'app.footer.chinamirror': '国内镜像站点 🇨🇳',
27 | 'app.footer.scaffolds': '脚手架市场',
28 | 'app.footer.links': '相关站点',
29 | 'app.footer.data-vis': '蚂蚁数据可视化方案',
30 | 'app.footer.eggjs': '企业级 Node Web 开发框架',
31 | 'app.footer.landing': '首页模板集',
32 | 'app.footer.kitchen': 'Sketch 工具集',
33 | 'app.footer.antd-library': 'Axure 部件库',
34 | 'app.footer.umi': 'React 应用开发框架',
35 | 'app.footer.dva': '数据流前端框架',
36 | 'app.footer.design-platform': '蚂蚁金服设计平台',
37 | 'app.footer.antux': '页面逻辑素材',
38 | 'app.footer.community': '社区',
39 | 'app.footer.issues': '讨论列表',
40 | 'app.footer.work-with-us': '加入我们',
41 | 'app.footer.author': '蚂蚁金服体验技术部出品 @ AFX',
42 | 'app.footer.resources': '相关资源',
43 | 'app.footer.more-product': '更多产品',
44 | 'app.footer.yuque': '语雀',
45 | 'app.footer.yuque.slogan': '知识创作·协作平台',
46 | 'app.footer.fengdie': '云凤蝶',
47 | 'app.footer.fengdie.slogan': '移动建站平台',
48 | 'app.footer.seeconf': '蚂蚁体验科技大会',
49 | 'app.footer.xcloud': '蚂蚁体验云',
50 | },
51 | };
52 |
--------------------------------------------------------------------------------
/theme.js:
--------------------------------------------------------------------------------
1 | module.exports = () => {
2 | return {
3 | '@primary-color': '#019BF0',
4 | '@text-color': '#666',
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint no-param-reassign: 0 */
2 | // This config is for building dist files
3 | const getWebpackConfig = require('antd-tools/lib/getWebpackConfig');
4 |
5 | const { webpack } = getWebpackConfig;
6 |
7 | // noParse still leave `require('./locale' + name)` in dist files
8 | // ignore is better: http://stackoverflow.com/q/25384360
9 | function ignoreMomentLocale(webpackConfig) {
10 | delete webpackConfig.module.noParse;
11 | webpackConfig.plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
12 | }
13 |
14 | function externalMoment(config) {
15 | config.externals.moment = {
16 | root: 'moment',
17 | commonjs2: 'moment',
18 | commonjs: 'moment',
19 | amd: 'moment',
20 | };
21 | }
22 |
23 | const webpackConfig = getWebpackConfig(false);
24 | if (process.env.RUN_ENV === 'PRODUCTION') {
25 | webpackConfig.forEach((config) => {
26 | ignoreMomentLocale(config);
27 | externalMoment(config);
28 | });
29 | }
30 |
31 | module.exports = webpackConfig;
32 |
--------------------------------------------------------------------------------