rc-tween-one
Version:
tween-one anim component for react
297 lines (258 loc) • 10.7 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _TweenOne = require('./TweenOne');
var _TweenOne2 = _interopRequireDefault(_TweenOne);
var _util = require('./util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function noop() {}
var TweenOneGroup = function (_Component) {
(0, _inherits3['default'])(TweenOneGroup, _Component);
function TweenOneGroup(props) {
(0, _classCallCheck3['default'])(this, TweenOneGroup);
var _this = (0, _possibleConstructorReturn3['default'])(this, (TweenOneGroup.__proto__ || Object.getPrototypeOf(TweenOneGroup)).call(this, props));
_initialiseProps.call(_this);
_this.keysToEnter = [];
_this.keysToLeave = [];
_this.saveTweenTag = {};
_this.onEnterBool = false;
_this.animQueue = [];
_this.isTween = {};
// 第一进入,appear 为 true 时默认用 enter 或 tween-one 上的效果
var children = (0, _util.toArrayChildren)((0, _util.getChildrenFromProps)(_this.props));
_this.originalChildren = (0, _util.toArrayChildren)((0, _util.getChildrenFromProps)(_this.props));
_this.currentChildren = (0, _util.toArrayChildren)((0, _util.getChildrenFromProps)(_this.props));
_this.state = {
children: children
};
return _this;
}
(0, _createClass3['default'])(TweenOneGroup, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.onEnterBool = true;
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var nextChildren = (0, _util.toArrayChildren)(nextProps.children);
if (Object.keys(this.isTween).length && !nextProps.exclusive) {
this.animQueue.push(nextChildren);
return;
}
var currentChildren = (0, _util.toArrayChildren)(nextProps.exclusive ? this.originalChildren : this.state.children);
this.changeChildren(nextChildren, currentChildren);
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
this.originalChildren = (0, _util.toArrayChildren)((0, _util.getChildrenFromProps)(this.props));
}
}, {
key: 'changeChildren',
value: function changeChildren(nextChildren, currentChildren) {
var _this2 = this;
var newChildren = (0, _util.mergeChildren)(currentChildren, nextChildren);
this.keysToEnter = [];
this.keysToLeave = [];
nextChildren.forEach(function (c) {
if (!c) {
return;
}
var key = c.key;
var hasPrev = (0, _util.findChildInChildrenByKey)(currentChildren, key);
// 如果当前 key 已存在 saveTweenTag 里,,刷新 child;
if (_this2.saveTweenTag[key]) {
_this2.saveTweenTag[key] = _react2['default'].cloneElement(_this2.saveTweenTag[key], {}, c);
}
if (!hasPrev && key) {
_this2.keysToEnter.push(key);
}
});
currentChildren.forEach(function (c) {
if (!c) {
return;
}
var key = c.key;
var hasNext = (0, _util.findChildInChildrenByKey)(nextChildren, key);
if (!hasNext && key) {
_this2.keysToLeave.push(key);
delete _this2.saveTweenTag[key];
}
});
this.currentChildren = newChildren;
this.setState({
children: newChildren
});
}
}, {
key: 'render',
value: function render() {
var childrenToRender = this.getChildrenToRender(this.state.children);
if (!this.props.component) {
return childrenToRender[0] || null;
}
var componentProps = (0, _extends3['default'])({}, this.props);
['component', 'componentProps', 'appear', 'enter', 'leave', 'animatingClassName', 'onEnd', 'exclusive'].forEach(function (key) {
return delete componentProps[key];
});
return (0, _react.createElement)(this.props.component, (0, _extends3['default'])({}, componentProps, this.props.componentProps), childrenToRender);
}
}]);
return TweenOneGroup;
}(_react.Component);
var _initialiseProps = function _initialiseProps() {
var _this3 = this;
this.onChange = function (animation, key, type, obj) {
var length = (0, _util.dataToArray)(animation).length;
var tag = obj.target;
var classIsSvg = typeof tag.className === 'object' && 'baseVal' in tag.className;
var isEnter = type === 'enter' || type === 'appear';
if (obj.mode === 'onStart') {
if (classIsSvg) {
tag.className.baseVal = _this3.setClassName(tag.className.baseVal, isEnter);
} else {
tag.className = _this3.setClassName(tag.className, isEnter);
}
} else if (obj.index === length - 1 && obj.mode === 'onComplete') {
delete _this3.isTween[key];
if (classIsSvg) {
tag.className.baseVal = tag.className.baseVal.replace(_this3.props.animatingClassName[isEnter ? 0 : 1], '').trim();
} else {
tag.className = tag.className.replace(_this3.props.animatingClassName[isEnter ? 0 : 1], '').trim();
}
if (type === 'enter') {
_this3.keysToEnter.splice(_this3.keysToEnter.indexOf(key), 1);
if (!_this3.keysToEnter.length) {
_this3.reAnimQueue();
}
} else if (type === 'leave') {
_this3.keysToLeave.splice(_this3.keysToLeave.indexOf(key), 1);
_this3.currentChildren = _this3.currentChildren.filter(function (child) {
return key !== child.key;
});
if (!_this3.keysToLeave.length) {
var currentChildrenKeys = _this3.currentChildren.map(function (item) {
return item.key;
});
Object.keys(_this3.saveTweenTag).forEach(function ($key) {
if (currentChildrenKeys.indexOf($key) === -1) {
delete _this3.saveTweenTag[$key];
}
});
_this3.setState({
children: _this3.currentChildren
}, _this3.reAnimQueue);
}
}
var _obj = { key: key, type: type };
_this3.props.onEnd(_obj);
}
};
this.setClassName = function (name, isEnter) {
var className = name.replace(_this3.props.animatingClassName[isEnter ? 1 : 0], '').trim();
if (className.indexOf(_this3.props.animatingClassName[isEnter ? 0 : 1]) === -1) {
className = (className + ' ' + _this3.props.animatingClassName[isEnter ? 0 : 1]).trim();
}
return className;
};
this.getTweenChild = function (child) {
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var key = child.key;
_this3.saveTweenTag[key] = _react2['default'].createElement(_TweenOne2['default'], (0, _extends3['default'])({}, props, {
key: key,
component: null
}), child);
return _this3.saveTweenTag[key];
};
this.getCoverAnimation = function (child, i, type) {
var animation = void 0;
animation = type === 'leave' ? _this3.props.leave : _this3.props.enter;
if (type === 'appear') {
var appear = (0, _util.transformArguments)(_this3.props.appear, child.key, i);
animation = appear && _this3.props.enter || null;
}
var animate = (0, _util.transformArguments)(animation, child.key, i);
var onChange = _this3.onChange.bind(_this3, animate, child.key, type);
var props = {
key: child.key,
animation: animate,
onChange: onChange,
resetStyle: _this3.props.exclusive
};
if (_this3.keysToEnter.concat(_this3.keysToLeave).indexOf(child.key) >= 0 || !_this3.onEnterBool && animation) {
if (!_this3.saveTweenTag[child.key]) {
_this3.isTween[child.key] = type;
}
}
var children = _this3.getTweenChild(child, props);
return children;
};
this.getChildrenToRender = function (children) {
return children.map(function (child, i) {
if (!child || !child.key) {
return child;
}
var key = child.key;
if (_this3.keysToLeave.indexOf(key) >= 0) {
return _this3.getCoverAnimation(child, i, 'leave');
} else if ((_this3.keysToEnter.indexOf(key) >= 0 || _this3.isTween[key] && _this3.keysToLeave.indexOf(key) === -1) && !(_this3.isTween[key] === 'enter' && _this3.saveTweenTag[key])) {
/**
* 1. 在 key 在 enter 里。
* 2. 出场未结束,触发进场, this.isTween[key] 为 leave, key 在 enter 里。
* 3. 状态为 enter 且 tweenTag 里有值时,不执行重载动画属性,直接调用 tweenTag 里的。
*/
return _this3.getCoverAnimation(child, i, 'enter');
} else if (!_this3.onEnterBool) {
return _this3.getCoverAnimation(child, i, 'appear');
}
return _this3.saveTweenTag[key];
});
};
this.reAnimQueue = function () {
if (!Object.keys(_this3.isTween).length && _this3.animQueue.length) {
_this3.changeChildren(_this3.animQueue[_this3.animQueue.length - 1], _this3.state.children);
_this3.animQueue = [];
}
};
};
TweenOneGroup.propTypes = {
component: _propTypes2['default'].any,
componentProps: _propTypes2['default'].object,
children: _propTypes2['default'].any,
style: _propTypes2['default'].object,
appear: _propTypes2['default'].bool,
enter: _propTypes2['default'].any,
leave: _propTypes2['default'].any,
animatingClassName: _propTypes2['default'].array,
onEnd: _propTypes2['default'].func,
exclusive: _propTypes2['default'].bool
};
TweenOneGroup.defaultProps = {
component: 'div',
componentProps: {},
appear: true,
animatingClassName: ['tween-one-entering', 'tween-one-leaving'],
enter: { x: 50, opacity: 0, type: 'from' },
leave: { x: -50, opacity: 0 },
onEnd: noop,
exclusive: false
};
TweenOneGroup.isTweenOneGroup = true;
exports['default'] = TweenOneGroup;
module.exports = exports['default'];