timingKeyframe.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { deepMix } from '@antv/util';
  2. function range(direction, iterationCount, keyframeCount) {
  3. const start = 0;
  4. const end = keyframeCount;
  5. const normal = [start, end];
  6. const reverse = [-end + 1, -start + 1];
  7. if (direction === 'normal')
  8. return normal;
  9. if (direction === 'reverse')
  10. return reverse;
  11. if (direction === 'alternate') {
  12. return iterationCount % 2 === 0 ? normal : reverse;
  13. }
  14. if (direction === 'reverse-alternate') {
  15. return iterationCount % 2 === 0 ? reverse : normal;
  16. }
  17. }
  18. /**
  19. * Set animation options for all descendants.
  20. */
  21. function setAnimation(node, duration, easing) {
  22. const discovered = [node];
  23. while (discovered.length) {
  24. const n = discovered.pop();
  25. n.animate = deepMix({
  26. enter: {
  27. duration,
  28. },
  29. update: {
  30. duration,
  31. easing,
  32. type: 'morphing',
  33. fill: 'both',
  34. },
  35. exit: {
  36. type: 'fadeOut',
  37. duration,
  38. },
  39. }, n.animate || {});
  40. const { children } = n;
  41. if (Array.isArray(children))
  42. discovered.push(...children);
  43. }
  44. return node;
  45. }
  46. /**
  47. * @todo More options, such as fill, totalDuration...
  48. */
  49. export const TimingKeyframe = () => {
  50. return (options) => {
  51. const { children = [], duration = 1000, iterationCount = 1, direction = 'normal', easing = 'ease-in-out-sine', } = options;
  52. const n = children.length;
  53. if (!Array.isArray(children) || n === 0)
  54. return [];
  55. const { key } = children[0];
  56. const newChildren = children
  57. .map((d) => (Object.assign(Object.assign({}, d), { key })))
  58. .map((d) => setAnimation(d, duration, easing));
  59. return function* () {
  60. let count = 0;
  61. let prevIndex;
  62. while (iterationCount === 'infinite' || count < iterationCount) {
  63. const [start, end] = range(direction, count, n);
  64. for (let i = start; i < end; i += 1) {
  65. // For reverse direction, the range is from negative to negative
  66. // so the absolute value of i is the real index for newChildren.
  67. const index = Math.abs(i);
  68. // This is for preventing alternate or reverse-alternate keyframe
  69. // to yield two same node one by one when the direction change.
  70. if (prevIndex !== index)
  71. yield newChildren[index];
  72. prevIndex = index;
  73. }
  74. count++;
  75. }
  76. };
  77. };
  78. };
  79. TimingKeyframe.props = {};
  80. //# sourceMappingURL=timingKeyframe.js.map