Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ Animate React Component in queue, thanks to [rc-animate](https://github.com/reac
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][coveralls-image]][coveralls-url]
[![gemnasium deps][gemnasium-image]][gemnasium-url]
[![node version][node-image]][node-url]
[![npm download][download-image]][download-url]

Expand All @@ -16,8 +15,6 @@ Animate React Component in queue, thanks to [rc-animate](https://github.com/reac
[travis-url]: https://travis-ci.org/react-component/queue-anim
[coveralls-image]: https://img.shields.io/coveralls/react-component/queue-anim.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/react-component/queue-anim?branch=master
[gemnasium-image]: http://img.shields.io/gemnasium/react-component/queue-anim.svg?style=flat-square
[gemnasium-url]: https://gemnasium.com/react-component/queue-anim
[node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square
[node-url]: http://nodejs.org/download/
[download-image]: https://img.shields.io/npm/dm/rc-queue-anim.svg?style=flat-square
Expand Down Expand Up @@ -57,6 +54,8 @@ ReactDom.render(

## API

> You must provide the key attribute for all children of QueueAnim, children would not peform any animation without key.

| props | type | default | description |
|------------|----------------|---------|----------------|
| type | string / array | `right` | Animation Styles <br/>`alpha` `left` `right` `top` `bottom` `scale` `scaleBig` `scaleX` `scaleY`|
Expand All @@ -74,8 +73,6 @@ ReactDom.render(

> Above props support array format, like `['left', 'top']`, the secord item is leave config. [Demo](http://react-component.github.io/queue-anim/examples/enter-leave.html)

You must provide the key attribute for all children of QueueAnim, children would not peform any animation without key.

### animConfig

**Data fall into three categories:**
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rc-queue-anim",
"version": "1.5.0",
"version": "1.6.0",
"description": "Queue animation component for react",
"keywords": [
"react",
Expand Down Expand Up @@ -52,7 +52,7 @@
"start": "rc-tools run server",
"compile": "rc-tools run compile --babel-runtime",
"pub": "rc-tools run pub --babel-runtime",
"lint": "rc-tools run lint",
"lint": "rc-tools run lint --fix",
"karma": "rc-test run karma",
"saucelabs": "rc-test run saucelabs",
"test": "rc-test run test",
Expand All @@ -79,6 +79,6 @@
"dependencies": {
"babel-runtime": "6.x",
"prop-types": "^15.6.0",
"rc-tween-one": "^1.7.0"
"rc-tween-one": "^1.8.0"
}
}
96 changes: 78 additions & 18 deletions src/QueueAnim.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import React, { createElement } from 'react';
import PropTypes from 'prop-types';
import TweenOne, { ticker } from 'rc-tween-one';
Expand Down Expand Up @@ -49,14 +50,58 @@ class QueueAnim extends React.Component {
onEnd: noop,
appear: true,
};

constructor(props) {
super(props);
/**
* @param oneEnter
* 记录第一次进入;
*/
this.oneEnter = false;
this.tweenToShow = {};
/**
* @param tweenToEnter;
* 记录强制切换时是否需要添加 animation;
* 如 enter 后, leave -> enter,样式是没有发生变化,就不需要添加 animation 属性。
*/
this.tweenToEnter = {};
/**
* @param leaveUnfinishedChild;
* 记录多次切换,出场没完成动画的 key。
*/
this.leaveUnfinishedChild = [];
/**
* @param saveTweenOneTag;
* 记录 TweenOne 标签,在 leaveUnfinishedChild 里使用,残留的元素不需要考虑 props 的变更。
*/
this.saveTweenOneTag = {};
/**
* @param unwantedStart;
* 记录 animation 里是否需要 startAnim;
* 修复进场时, 时间不准的问题;
* -> 进: 需要;
* -> 进 -> 进: 需要;
* -> 进 -> 出: 不需要;
* -> 进 -> 出 -> 进: 不需要;
*/
this.unwantedStart = {};
/**
* @param keysToEnter;
* 记录进场的 key;
*/
this.keysToEnter = [];
/**
* @param keysToLeave;
* 记录出场的 key;
*/
this.keysToLeave = [];
/**
* @param keysToEnterPaused;
* 记录在进入时是否处理暂停状态
*/
this.keysToEnterPaused = {};
/**
* @param placeholderTimeoutIds;
* 进场时 deley 的 timeout 记录;
*/
this.placeholderTimeoutIds = {};
// 第一次进入,默认进场
const children = toArrayChildren(getChildrenFromProps(props));
Expand Down Expand Up @@ -97,6 +142,7 @@ class QueueAnim extends React.Component {
const leaveChild = this.state.children.filter(item =>
item && this.keysToLeave.indexOf(item.key) >= 0
);
this.leaveUnfinishedChild = leaveChild.map(item => item.key);
currentChildren = mergeChildren(currentChildren, leaveChild);
}
const newChildren = mergeChildren(
Expand Down Expand Up @@ -210,8 +256,9 @@ class QueueAnim extends React.Component {
const end = type === 'enter' ? 0 : 1;
let startAnim = this.getAnimData(props, key, i, enterOrLeave, start);
const animate = this.getAnimData(props, key, i, enterOrLeave, end);
startAnim = (type === 'enter' && props.enterForcedRePlay) || !this.tweenToShow[key] ?
startAnim : {};
startAnim = type === 'enter' && (props.enterForcedRePlay
|| !this.unwantedStart[key]) ?
startAnim : null;
let ease = transformArguments(props.ease, key, i)[enterOrLeave];
const duration = transformArguments(props.duration, key, i)[enterOrLeave];
if (Array.isArray(ease)) {
Expand Down Expand Up @@ -293,8 +340,20 @@ class QueueAnim extends React.Component {
}
let i = this.keysToLeave.indexOf(key);
let animation;
const isFunc = typeof child.type === 'function';
const forcedJudg = isFunc ? {} : null;
if (isFunc) {
Object.keys(child.type).forEach(name => {
if (typeDefault.indexOf(name) === -1) {
forcedJudg[name] = child.type[name];
}
});
}
// 处理出场
if (i >= 0) {
if (this.leaveUnfinishedChild.indexOf(key) >= 0) {
return this.saveTweenOneTag[key];
}
const interval = transformArguments(this.props.interval, key, i)[1];
let delay = transformArguments(this.props.delay, key, i)[1];
const order = this.props.leaveReverse ? (this.keysToLeave.length - i - 1) : i;
Expand All @@ -308,21 +367,18 @@ class QueueAnim extends React.Component {
} else {
animation = this.getTweenEnterOrLeaveData(key, i, 0, 'enter');
}
if (this.tweenToEnter[key]) {
// 如果是已进入的,将直接返回标签。。
return createElement(TweenOne,
{ key, component: child.type, forcedJudg, componentProps: child.props });
}
}
const paused = this.keysToEnterPaused[key] && !this.keysToLeave.indexOf(key) >= 0;

animation = paused ? null : animation;
const isFunc = typeof child.type === 'function';
const forcedJudg = isFunc ? {} : null;
if (isFunc) {
Object.keys(child.type).forEach(name => {
if (typeDefault.indexOf(name) === -1) {
forcedJudg[name] = child.type[name];
}
});
}
return createElement(TweenOne,
{ key, component: child.type, componentProps: child.props, forcedJudg, animation });
const tag = createElement(TweenOne,
{ key, component: child.type, id: key, forcedJudg, componentProps: child.props, animation });
this.saveTweenOneTag[key] = tag;
return tag;
};

performEnter = (key, i) => {
Expand Down Expand Up @@ -358,7 +414,6 @@ class QueueAnim extends React.Component {
if (elem.className.indexOf(animatingClassName[0]) === -1) {
elem.className = (`${elem.className} ${animatingClassName[0]}`).trim();
}
this.tweenToShow[key] = true;
}

enterComplete = (key, e) => {
Expand All @@ -367,6 +422,8 @@ class QueueAnim extends React.Component {
}
const elem = e.target;
elem.className = elem.className.replace(this.props.animatingClassName[0], '').trim();
this.tweenToEnter[key] = true;
this.unwantedStart[key] = true;
this.props.onEnd({ key, type: 'enter' });
}

Expand All @@ -377,6 +434,8 @@ class QueueAnim extends React.Component {
if (elem.className.indexOf(animatingClassName[1]) === -1) {
elem.className = (`${elem.className} ${animatingClassName[1]}`).trim();
}
this.unwantedStart[key] = true;
delete this.tweenToEnter[key];
}

leaveComplete = (key, e) => {
Expand All @@ -388,7 +447,8 @@ class QueueAnim extends React.Component {
delete childrenShow[key];
if (this.keysToLeave.indexOf(key) >= 0) {
this.keysToLeave.splice(this.keysToLeave.indexOf(key), 1);
delete this.tweenToShow[key];
delete this.saveTweenOneTag[key];
delete this.unwantedStart[key];
}
const needLeave = this.keysToLeave.some(c => childrenShow[c]);
if (!needLeave) {
Expand Down