rc-tween-one
Version:
tween-one anim component for react
288 lines (237 loc) • 10.4 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireWildcard(require("react"));
var _group = require("./utils/group");
var _common = require("./utils/common");
var _TweenOne = _interopRequireDefault(require("./TweenOne"));
var _excluded = ["component", "componentProps", "leave", "enter", "appear", "resetStyle", "animatingClassName", "onEnd", "exclusive"];
var TweenOneGroup = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
var _props$component = props.component,
component = _props$component === void 0 ? 'div' : _props$component,
_props$componentProps = props.componentProps,
componentProps = _props$componentProps === void 0 ? {} : _props$componentProps,
_props$leave = props.leave,
leaveAnim = _props$leave === void 0 ? {
x: -50,
opacity: 0
} : _props$leave,
_props$enter = props.enter,
enterAnim = _props$enter === void 0 ? {
x: 50,
opacity: 0,
type: 'from'
} : _props$enter,
_props$appear = props.appear,
appearBool = _props$appear === void 0 ? true : _props$appear,
_props$resetStyle = props.resetStyle,
resetStyle = _props$resetStyle === void 0 ? true : _props$resetStyle,
_props$animatingClass = props.animatingClassName,
animatingClassName = _props$animatingClass === void 0 ? ['tween-one-entering', 'tween-one-leaving'] : _props$animatingClass,
_props$onEnd = props.onEnd,
onEnd = _props$onEnd === void 0 ? function () {} : _props$onEnd,
_props$exclusive = props.exclusive,
exclusive = _props$exclusive === void 0 ? false : _props$exclusive,
tagProps = (0, _objectWithoutProperties2.default)(props, _excluded);
var keysToEnter = (0, _react.useRef)([]);
var keysToLeave = (0, _react.useRef)([]);
var saveTweenTag = (0, _react.useRef)({});
var oneEnter = (0, _react.useRef)(false);
var animQueue = (0, _react.useRef)([]);
var isTween = (0, _react.useRef)({});
var cChild = (0, _group.toArrayChildren)((0, _group.getChildrenFromProps)(props));
var currentChildren = (0, _react.useRef)(cChild);
var _useState = (0, _react.useState)(cChild),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
children = _useState2[0],
setChild = _useState2[1];
var getTweenChild = function getTweenChild(child) {
var p = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var key = child.key;
saveTweenTag.current[key] = /*#__PURE__*/_react.default.createElement(_TweenOne.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, p), {}, {
key: key,
component: null
}), child);
return saveTweenTag.current[key];
};
var setClassName = function setClassName(name, isEnter) {
var className = name.replace(animatingClassName[isEnter ? 1 : 0], '').trim();
if (className.indexOf(animatingClassName[isEnter ? 0 : 1]) === -1) {
className = "".concat(className, " ").concat(animatingClassName[isEnter ? 0 : 1]).trim();
}
return className;
};
var changeChildren = function changeChildren(nextChildren, currentChild) {
var newChildren = (0, _group.mergeChildren)(currentChild, nextChildren);
keysToEnter.current = [];
keysToLeave.current = [];
nextChildren.forEach(function (c) {
if (!c) {
return;
}
var key = c.key;
var hasPrev = (0, _group.findChildInChildrenByKey)(currentChild, key); // 如果当前 key 已存在 saveTweenTag 里,,刷新 child;
if (key && saveTweenTag.current[key]) {
saveTweenTag.current[key] = /*#__PURE__*/_react.default.cloneElement(saveTweenTag.current[key], {}, c);
}
if (!hasPrev && key) {
keysToEnter.current.push(key);
}
});
currentChild.forEach(function (c) {
if (!c) {
return;
}
var key = c.key;
var hasNext = (0, _group.findChildInChildrenByKey)(nextChildren, key);
if (!hasNext && key) {
keysToLeave.current.push(key);
delete saveTweenTag.current[key];
}
});
return newChildren;
};
var reAnimQueue = function reAnimQueue() {
if (!Object.keys(isTween.current).length && animQueue.current.length) {
// 取最后一个继续动画;
var child = changeChildren(animQueue.current[animQueue.current.length - 1], currentChildren.current);
setChild(child);
animQueue.current = [];
}
};
var onChange = function onChange(key, type, obj) {
var tag = obj.targets;
var classIsSvg = (0, _typeof2.default)(tag.className) === 'object' && 'baseVal' in tag.className;
var isEnter = type === 'enter' || type === 'appear';
if (key && obj.mode === 'onTimelineComplete') {
delete isTween.current[key];
if (classIsSvg) {
tag.className.baseVal = tag.className.baseVal.replace(animatingClassName[isEnter ? 0 : 1], '').trim();
} else {
tag.className = tag.className.replace(animatingClassName[isEnter ? 0 : 1], '').trim();
}
if (isEnter) {
keysToEnter.current.splice(keysToEnter.current.indexOf(key), 1);
if (!keysToEnter.current.length) {
// enter 不会触发 did update, 手动触发一次;
reAnimQueue();
}
} else if (type === 'leave') {
keysToLeave.current.splice(keysToLeave.current.indexOf(key), 1);
currentChildren.current = currentChildren.current.filter(function (child) {
return key !== child.key;
});
if (!keysToLeave.current.length) {
var currentChildrenKeys = currentChildren.current.map(function (item) {
return item.key;
});
Object.keys(saveTweenTag.current).forEach(function ($key) {
if (currentChildrenKeys.indexOf($key) === -1) {
delete saveTweenTag.current[$key];
}
});
setChild(currentChildren.current);
}
}
onEnd({
key: key,
type: type,
target: obj.targets
});
}
};
var getCoverAnimation = function getCoverAnimation(child, i, type) {
var animation = type === 'leave' ? leaveAnim : enterAnim;
if (type === 'appear') {
var appear = (0, _group.transformArguments)(appearBool, child.key, i);
animation = appear && enterAnim || null;
}
var animate = (0, _group.transformArguments)(animation, child.key, i);
var onChangeCb = function onChangeCb(obj) {
onChange(child.key, type, obj);
};
var className = type === 'appear' && !appearBool ? child.props.className : setClassName(child.props.className || '', type === 'enter' || type === 'appear') || undefined;
var p = {
key: child.key,
animation: animate,
onChangeTimeline: onChangeCb,
resetStyle: resetStyle,
className: className
};
if (child.key && keysToEnter.current.concat(keysToLeave.current).indexOf(child.key) >= 0 || !oneEnter.current && animation) {
if (child.key && !saveTweenTag.current[child.key]) {
isTween.current[child.key] = type;
}
}
return getTweenChild(child, p);
};
(0, _common.useIsomorphicLayoutEffect)(function () {
if (oneEnter.current) {
var nextChild = (0, _group.toArrayChildren)(props.children).filter(function (c) {
return c;
});
var currentChild = (0, _group.toArrayChildren)(currentChildren.current); // 如果还在动画,暂存动画队列里,等前一次动画结束后再启动最后次的更新动画
if (Object.keys(isTween.current).length && !exclusive) {
animQueue.current.push(nextChild);
} else {
setChild(changeChildren(nextChild, currentChild));
}
}
}, [props.children]);
(0, _common.useIsomorphicLayoutEffect)(function () {
reAnimQueue();
});
(0, _react.useEffect)(function () {
oneEnter.current = true;
}, []);
currentChildren.current = children;
var childrenToRender = children.map(function (child, i) {
if (!child || !child.key) {
return child;
}
var key = child.key;
if (keysToLeave.current.indexOf(key) >= 0) {
return getCoverAnimation(child, keysToLeave.current.indexOf(key), 'leave');
}
if ((keysToEnter.current.indexOf(key) >= 0 || isTween.current[key] && keysToLeave.current.indexOf(key) === -1) && !(isTween.current[key] === 'enter' && saveTweenTag.current[key])) {
/**
* 1. 在 key 在 enter 里。
* 2. 出场未结束,触发进场, this.isTween[key] 为 leave, key 在 enter 里。
* 3. 状态为 enter 且 tweenTag 里有值时,不执行重载动画属性,直接调用 tweenTag 里的。
*/
return getCoverAnimation(child, keysToEnter.current.indexOf(key), 'enter');
}
if (!oneEnter.current) {
return getCoverAnimation(child, i, 'appear');
}
return saveTweenTag.current[key];
});
if (_common.windowIsUndefined) {
if (!component) {
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, props.children);
}
return /*#__PURE__*/(0, _react.createElement)(component, (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, tagProps), componentProps), {}, {
ref: ref
}), props.children);
}
if (!component) {
return childrenToRender[0] ? /*#__PURE__*/(0, _react.cloneElement)(childrenToRender[0], {
ref: ref
}) : null;
}
return /*#__PURE__*/(0, _react.createElement)(component, (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, tagProps), componentProps), {}, {
ref: ref
}), childrenToRender);
});
TweenOneGroup.displayName = 'TweenOneGroup';
TweenOneGroup.isTweenOneGroup = true;
var _default = TweenOneGroup;
exports.default = _default;