UNPKG

17.3 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
6
7Object.defineProperty(exports, "__esModule", {
8 value: true
9});
10exports.default = void 0;
11
12var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
13
14var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
15
16var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
17
18var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
19
20var _react = require("react");
21
22var _reactDom = require("react-dom");
23
24var _tweenOne = _interopRequireWildcard(require("tween-one"));
25
26var _utils = require("./utils");
27
28var _animTypes = _interopRequireDefault(require("./animTypes"));
29
30var _excluded = ["component", "componentProps", "interval", "duration", "delay", "type", "animConfig", "ease", "leaveReverse", "forcedReplay", "animatingClassName", "onEnd", "appear"];
31
32var noop = function noop() {};
33
34var _default = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
35 var _props$component = props.component,
36 component = _props$component === void 0 ? 'div' : _props$component,
37 _props$componentProps = props.componentProps,
38 componentProps = _props$componentProps === void 0 ? {} : _props$componentProps,
39 _props$interval = props.interval,
40 interval = _props$interval === void 0 ? 100 : _props$interval,
41 _props$duration = props.duration,
42 duration = _props$duration === void 0 ? 450 : _props$duration,
43 _props$delay = props.delay,
44 delay = _props$delay === void 0 ? 0 : _props$delay,
45 _props$type = props.type,
46 type = _props$type === void 0 ? 'right' : _props$type,
47 _props$animConfig = props.animConfig,
48 animConfig = _props$animConfig === void 0 ? null : _props$animConfig,
49 _props$ease = props.ease,
50 ease = _props$ease === void 0 ? 'easeOutQuart' : _props$ease,
51 _props$leaveReverse = props.leaveReverse,
52 leaveReverse = _props$leaveReverse === void 0 ? false : _props$leaveReverse,
53 _props$forcedReplay = props.forcedReplay,
54 forcedReplay = _props$forcedReplay === void 0 ? false : _props$forcedReplay,
55 _props$animatingClass = props.animatingClassName,
56 animatingClassName = _props$animatingClass === void 0 ? ['queue-anim-entering', 'queue-anim-leaving'] : _props$animatingClass,
57 _props$onEnd = props.onEnd,
58 onEnd = _props$onEnd === void 0 ? noop : _props$onEnd,
59 _props$appear = props.appear,
60 appear = _props$appear === void 0 ? true : _props$appear,
61 tagProps = (0, _objectWithoutProperties2.default)(props, _excluded);
62 /**
63 * @param childrenShow;
64 * 记录 animation 里是否需要 startAnim;
65 * 当前元素是否处在显示状态
66 * enterBegin 到 leaveComplete 之前都处于显示状态
67 */
68
69 var childrenShow = (0, _react.useRef)({});
70 /**
71 * @param keysToEnter;
72 * 记录进场的 key;
73 */
74
75 var keysToEnter = (0, _react.useRef)([]);
76 var recordKeysToEnter = (0, _react.useRef)([]);
77 /**
78 * @param keysToLeave;
79 * 记录出场的 key;
80 */
81
82 var keysToLeave = (0, _react.useRef)([]);
83 var recordKeysToLeave = (0, _react.useRef)([]);
84 /**
85 * @param placeholderTimeoutIds;
86 * 进场时 deley 的 timeout 记录;
87 */
88
89 var placeholderTimeoutIds = (0, _react.useRef)({});
90 /**
91 * @param childRefs;
92 * 储存 children 的 ref;
93 */
94
95 var childRefs = (0, _react.useRef)({});
96 /**
97 * @param recordAnimKeys;
98 * 记录启动动画 key
99 */
100
101 var recordAnimKeys = (0, _react.useRef)({});
102 /**
103 * @param recordAnimKeys;
104 * 记录启动动画 key
105 */
106
107 var recordTweenKeys = (0, _react.useRef)({});
108 /**
109 * @param oneEnterBool
110 * 记录第一次进入
111 */
112
113 var oneEnterBool = (0, _react.useRef)(false);
114 var originalChildren = (0, _react.useRef)([]);
115
116 var _useState = (0, _react.useState)(),
117 _useState2 = (0, _slicedToArray2.default)(_useState, 2),
118 child = _useState2[0],
119 setChild = _useState2[1];
120
121 var _useState3 = (0, _react.useState)({}),
122 _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
123 childShow = _useState4[0],
124 setChildShow = _useState4[1];
125
126 var getTweenSingleConfig = function getTweenSingleConfig(data, num, enterOrLeave) {
127 var obj = {};
128 Object.keys(data).forEach(function (key) {
129 if (Array.isArray(data[key])) {
130 obj[key] = data[key][num];
131 } else if (!enterOrLeave && !num || enterOrLeave && num) {
132 obj[key] = data[key];
133 }
134 });
135 return obj;
136 };
137
138 var getTweenAnimConfig = function getTweenAnimConfig(data, num, enterOrLeave) {
139 if (Array.isArray(data)) {
140 return data.map(function (item) {
141 return getTweenSingleConfig(item, num, enterOrLeave);
142 });
143 }
144
145 return getTweenSingleConfig(data, num, enterOrLeave);
146 };
147
148 var getTweenType = function getTweenType($type, num) {
149 var data = _animTypes.default[$type];
150 return getTweenAnimConfig(data, num);
151 };
152
153 var getAnimData = function getAnimData(key, i, enterOrLeave, startOrEnd) {
154 return (
155 /**
156 * transformArguments 第一个为 enter, 第二个为 leave;
157 * getTweenAnimConfig or getTweenType 第一个为到达的位置, 第二个为开始的位置。
158 * 用 tween-one 的数组来实现老的动画逻辑。。。
159 */
160 animConfig ? getTweenAnimConfig((0, _utils.transformArguments)(animConfig, key, i)[enterOrLeave], startOrEnd, enterOrLeave) : getTweenType((0, _utils.transformArguments)(type, key, i)[enterOrLeave], startOrEnd)
161 );
162 };
163
164 var getTweenData = function getTweenData(key, i, $type) {
165 var enterOrLeave = $type === 'enter' ? 0 : 1;
166 var start = $type === 'enter' ? 1 : 0;
167 var end = $type === 'enter' ? 0 : 1;
168 var animate = getAnimData(key, i, enterOrLeave, end);
169 var startAnim = $type === 'enter' && (forcedReplay || !childrenShow.current[key]) ? getAnimData(key, i, enterOrLeave, start) : null;
170 var $ease = (0, _utils.transformArguments)(ease, key, i)[enterOrLeave];
171 var $duration = (0, _utils.transformArguments)(duration, key, i)[enterOrLeave];
172
173 if (Array.isArray(ease) && (ease.length > 2 || Array.isArray(ease[0]))) {
174 $ease = $ease.map(function (num) {
175 return num * 100;
176 });
177 $ease = "M0,100C".concat($ease[0], ",").concat(100 - $ease[1], ",").concat($ease[2], ",").concat(100 - $ease[3], ",100,0");
178 }
179
180 return {
181 startAnim: startAnim,
182 animate: animate,
183 ease: $ease,
184 duration: $duration
185 };
186 };
187
188 var enterBegin = function enterBegin(key, e) {
189 var elem = e.targets;
190 elem.className = elem.className.replace(animatingClassName[1], '');
191
192 if (elem.className.indexOf(animatingClassName[0]) === -1) {
193 elem.className = "".concat(elem.className, " ").concat(animatingClassName[0]).trim();
194 }
195
196 if (keysToEnter.current.indexOf(key) >= 0) {
197 keysToEnter.current.splice(keysToEnter.current.indexOf(key), 1);
198 }
199
200 childrenShow.current[key] = true;
201 };
202
203 var enterComplete = function enterComplete(key, e) {
204 if (keysToLeave.current.indexOf(key) >= 0) {
205 return;
206 }
207
208 var elem = e.targets;
209 elem.className = elem.className.replace(animatingClassName[0], '').trim();
210 delete recordTweenKeys.current[key];
211 onEnd({
212 key: key,
213 type: 'enter',
214 target: elem
215 });
216 };
217
218 var leaveBegin = function leaveBegin(key, e) {
219 var elem = e.targets;
220 elem.className = elem.className.replace(animatingClassName[0], '');
221
222 if (elem.className.indexOf(animatingClassName[1]) === -1) {
223 elem.className = "".concat(elem.className, " ").concat(animatingClassName[1]).trim();
224 }
225 };
226
227 var leaveComplete = function leaveComplete(key, e) {
228 // 切换时同时触发 onComplete。 手动跳出。。。
229 (0, _utils.toArrayChildren)(props.children).findIndex(function (c) {
230 return c && c.key === key;
231 });
232
233 if ((0, _utils.toArrayChildren)(props.children).findIndex(function (c) {
234 return c && c.key === key;
235 }) >= 0) {
236 return;
237 }
238
239 delete childrenShow.current[key];
240 delete recordTweenKeys.current[key];
241 originalChildren.current = originalChildren.current.filter(function (c) {
242 return c.key !== key;
243 }); // 这里不用启动动画,,直接删;
244
245 if (keysToLeave.current.indexOf(key) >= 0) {
246 keysToLeave.current.splice(keysToLeave.current.indexOf(key), 1);
247 }
248
249 var needLeave = keysToLeave.current.some(function (c) {
250 return childShow[c];
251 });
252
253 if (!needLeave) {
254 var currentChildren = (0, _utils.toArrayChildren)(props.children);
255 setChild(currentChildren);
256 setChildShow((0, _objectSpread2.default)({}, childrenShow.current));
257 recordKeysToLeave.current.forEach(function (k) {
258 delete recordAnimKeys.current[k];
259 });
260 }
261
262 var elem = e.targets;
263 elem.className = elem.className.replace(animatingClassName[1], '').trim();
264 onEnd({
265 key: key,
266 type: 'leave',
267 target: elem
268 });
269 };
270
271 var performEnterBegin = function performEnterBegin(key) {
272 childShow[key] = true;
273
274 _tweenOne.Ticker.clear(placeholderTimeoutIds.current[key]);
275
276 delete placeholderTimeoutIds.current[key];
277 setChildShow((0, _objectSpread2.default)({}, childShow));
278 };
279
280 var performEnter = function performEnter(key, i) {
281 var $interval = (0, _utils.transformArguments)(interval, key, i)[0];
282 var $delay = (0, _utils.transformArguments)(delay, key, i)[0];
283 placeholderTimeoutIds.current[key] = _tweenOne.Ticker.timeout(function () {
284 performEnterBegin(key);
285 }, $interval * i + $delay);
286 };
287
288 var performLeave = function performLeave(key) {
289 _tweenOne.Ticker.clear(placeholderTimeoutIds.current[key]);
290
291 delete placeholderTimeoutIds.current[key];
292 };
293
294 var getTweenOneEnterOrLeave = function getTweenOneEnterOrLeave(key, i, $delay, $type) {
295 var animateData = getTweenData(key, i, $type);
296
297 var onStart = function onStart(e) {
298 ($type === 'enter' ? enterBegin : leaveBegin)(key, e);
299 };
300
301 var onComplete = function onComplete(e) {
302 ($type === 'enter' ? enterComplete : leaveComplete)(key, e);
303 };
304
305 if (Array.isArray(animateData.animate)) {
306 var length = animateData.animate.length - 1;
307 var animation = animateData.animate.map(function (item, ii) {
308 return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, item), {}, {
309 startAt: animateData.startAnim ? animateData.startAnim[ii] : undefined,
310 duration: animateData.duration / length,
311 delay: !ii && $type === 'leave' ? $delay : 0,
312 onStart: !ii ? onStart : undefined,
313 onComplete: ii === length ? onComplete : undefined
314 });
315 });
316 return animation;
317 }
318
319 return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, animateData.animate), {}, {
320 startAt: animateData.startAnim || undefined,
321 ease: animateData.ease,
322 duration: animateData.duration,
323 onStart: onStart,
324 onComplete: onComplete,
325 delay: $delay
326 });
327 };
328
329 (0, _react.useEffect)(function () {
330 return function () {
331 Object.keys(recordTweenKeys.current).forEach(function (key) {
332 var tween = recordTweenKeys.current[key];
333
334 if (!tween) {
335 return;
336 }
337
338 tween.kill();
339 });
340 };
341 }, []);
342 (0, _react.useEffect)(function () {
343 var nextChildren = (0, _utils.toArrayChildren)(props.children).filter(function (c) {
344 return c;
345 });
346 var currentChildren = originalChildren.current.filter(function (item) {
347 return item;
348 });
349 var newChildren = (0, _utils.mergeChildren)(currentChildren, nextChildren);
350 var $keysToEnter = [];
351 var $keysToLeave = [];
352
353 if (!appear && !oneEnterBool.current) {
354 var $childShow = {};
355 newChildren.forEach(function (c) {
356 if (!c || !c.key) {
357 return;
358 }
359
360 $childShow[c.key] = true;
361 });
362 originalChildren.current = newChildren;
363 childrenShow.current = (0, _objectSpread2.default)({}, $childShow);
364 setChildShow($childShow);
365 } else {
366 // console.log(nextChildren, recordAnimKeys.current, keysToEnter.current, keysToLeave.current);
367 currentChildren.forEach(function (c) {
368 if (!c) {
369 return;
370 }
371
372 var key = c.key;
373 var hasNext = (0, _utils.findChildInChildrenByKey)(nextChildren, key);
374
375 if (!hasNext && key) {
376 $keysToLeave.push(key);
377
378 _tweenOne.Ticker.clear(placeholderTimeoutIds.current[key]);
379
380 delete placeholderTimeoutIds.current[key];
381 }
382 });
383 nextChildren.forEach(function (c) {
384 if (!c) {
385 return;
386 }
387
388 var key = c.key;
389 var hasPrev = (0, _utils.findChildInChildrenByKey)(currentChildren, key); // 如果 nextChildren 和当前的一致,且动画里是出场,改回进场;
390
391 if (!hasPrev && key || (!recordAnimKeys.current[key] || recordAnimKeys.current[key] === 'leave' || keysToEnter.current.indexOf(key) >= 0) && $keysToLeave.indexOf(key) === -1) {
392 $keysToEnter.push(key);
393 }
394 });
395 } // console.log('child update', $keysToEnter, $keysToLeave, newChildren);
396
397
398 keysToEnter.current = $keysToEnter; // keysToEnter 在启动时就会删除;
399
400 recordKeysToEnter.current = [].concat($keysToEnter);
401 keysToLeave.current = $keysToLeave;
402 recordKeysToLeave.current = [].concat($keysToLeave); // console.log($keysToEnter, $keysToLeave);
403
404 setChild(newChildren);
405 }, [props.children]);
406 (0, _react.useLayoutEffect)(function () {
407 originalChildren.current = child || [];
408
409 if (appear || oneEnterBool.current) {
410 var $keysToEnter = (0, _toConsumableArray2.default)(keysToEnter.current);
411 var $keysToLeave = (0, _toConsumableArray2.default)(keysToLeave.current);
412 $keysToEnter.forEach(performEnter);
413 $keysToLeave.forEach(performLeave);
414 }
415
416 if (child) {
417 oneEnterBool.current = true;
418 }
419 }, [child]);
420 (0, _react.useLayoutEffect)(function () {
421 if (child) {
422 child.forEach(function (item) {
423 var key = item.key;
424 var dom = childRefs.current[key];
425
426 if (!dom) {
427 return;
428 }
429
430 var animation;
431 var index = keysToLeave.current.indexOf(key); // children.findIndex(c => c.key === key);
432
433 var $interval = (0, _utils.transformArguments)(interval, key, index);
434 var $delay = (0, _utils.transformArguments)(delay, key, index); // 处理出场
435
436 if (index >= 0) {
437 if (recordAnimKeys.current[key] === 'leave') {
438 return;
439 }
440
441 var order = leaveReverse ? keysToLeave.current.length - index - 1 : index;
442 var d = $interval[1] * order + $delay[1];
443 animation = getTweenOneEnterOrLeave(key, index, d, 'leave');
444 recordAnimKeys.current[key] = 'leave';
445 } else {
446 if (recordAnimKeys.current[key] === 'enter' || keysToEnter.current.indexOf(key) === -1) {
447 return;
448 }
449
450 index = recordKeysToEnter.current.indexOf(key);
451
452 var _d = $interval[0] * index + $delay[0]; // console.log(recordAnimKeys.current[key], dom);
453
454
455 animation = getTweenOneEnterOrLeave(key, index, recordAnimKeys.current[key] === 'leave' ? _d : 0, 'enter');
456 recordAnimKeys.current[key] = 'enter';
457 }
458
459 if (recordTweenKeys.current[key]) {
460 recordTweenKeys.current[key].kill();
461 }
462
463 if (forcedReplay) {
464 var anim = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, Array.isArray(animation) ? animation[0].startAt : animation.startAt), {}, {
465 type: 'set'
466 });
467 (0, _tweenOne.default)(dom, {
468 animation: anim
469 });
470 }
471
472 recordTweenKeys.current[key] = (0, _tweenOne.default)(dom, {
473 animation: animation
474 });
475 });
476 }
477 }, [childShow, child]);
478 return (0, _react.useMemo)(function () {
479 // console.log('--------render--------', childShow);
480 if (_utils.windowIsUndefined) {
481 return /*#__PURE__*/(0, _react.createElement)(component, (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, tagProps), componentProps), {}, {
482 ref: ref
483 }));
484 }
485
486 var childrenToRender = (0, _utils.toArrayChildren)(child).map(function (item) {
487 if (!item || !item.key) {
488 return item;
489 }
490
491 return childShow[item.key] && /*#__PURE__*/(0, _react.cloneElement)(item, {
492 ref: function ref(c) {
493 childRefs.current[item.key] = c instanceof Element ? c : (0, _reactDom.findDOMNode)(c);
494
495 if (!c) {
496 delete childRefs.current[item.key];
497 }
498 },
499 key: item.key
500 });
501 });
502 var p = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, tagProps), componentProps), {}, {
503 ref: ref
504 });
505 return /*#__PURE__*/(0, _react.createElement)(component, p, childrenToRender);
506 }, [childShow, child]);
507});
508
509exports.default = _default;
\No newline at end of file