uvue.uts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // @ts-nocheck
  2. import {raf, cancelRaf} from '../raf'
  3. export class Timeline {
  4. state : string
  5. animations : Set<Animation> = new Set<Animation>()
  6. delAnimations : Animation[] = []
  7. startTimes : Map<Animation, number> = new Map<Animation, number>()
  8. pauseTime : number = 0
  9. pauseStart : number = Date.now()
  10. tickHandler : number = 0
  11. tickHandlers : number[] = []
  12. tick : (() => void) | null = null
  13. constructor() {
  14. this.state = 'Initiated';
  15. }
  16. start() {
  17. if (!(this.state === 'Initiated')) return;
  18. this.state = 'Started';
  19. let startTime = Date.now();
  20. this.pauseTime = 0;
  21. this.tick = () => {
  22. let now = Date.now();
  23. this.animations.forEach((animation : Animation) => {
  24. let t:number;
  25. const ani = this.startTimes.get(animation)
  26. if (ani == null) return
  27. if (ani < startTime) {
  28. t = now - startTime - animation.delay - this.pauseTime;
  29. } else {
  30. t = now - ani - animation.delay - this.pauseTime;
  31. }
  32. if (t > animation.duration) {
  33. this.delAnimations.push(animation)
  34. // 不能在 foreach 里面 对 集合进行删除操作
  35. // this.animations.delete(animation);
  36. t = animation.duration;
  37. }
  38. if (t > 0) animation.run(t);
  39. })
  40. // 不能在 foreach 里面 对 集合进行删除操作
  41. while (this.delAnimations.length > 0) {
  42. const animation = this.delAnimations.pop();
  43. if (animation == null) return
  44. this.animations.delete(animation);
  45. }
  46. clearTimeout(this.tickHandler);
  47. if (this.state != 'Started') return
  48. // this.tickHandler = setTimeout(() => {
  49. // this.tick!()
  50. // }, 1000 / 60)
  51. this.tickHandler = raf(()=> {
  52. this.tick!()
  53. })
  54. // this.tickHandlers.push(this.tickHandler)
  55. }
  56. this.tick!()
  57. }
  58. pause() {
  59. if (!(this.state === 'Started')) return;
  60. this.state = 'Paused';
  61. this.pauseStart = Date.now();
  62. // clearTimeout(this.tickHandler);
  63. cancelRaf(this.tickHandler);
  64. }
  65. resume() {
  66. if (!(this.state === 'Paused')) return;
  67. this.state = 'Started';
  68. this.pauseTime += Date.now() - this.pauseStart;
  69. this.tick!();
  70. }
  71. reset() {
  72. this.pause();
  73. this.state = 'Initiated';
  74. this.pauseTime = 0;
  75. this.pauseStart = 0;
  76. this.animations.clear()
  77. this.delAnimations.clear()
  78. this.startTimes.clear()
  79. this.tickHandler = 0;
  80. }
  81. add(animation : Animation, startTime ?: number | null) {
  82. if (startTime == null) startTime = Date.now();
  83. this.animations.add(animation);
  84. this.startTimes.set(animation, startTime);
  85. }
  86. }
  87. export class Animation {
  88. startValue : number
  89. endValue : number
  90. duration : number
  91. timingFunction : (t : number) => number
  92. delay : number
  93. template : (t : number) => void
  94. constructor(
  95. startValue : number,
  96. endValue : number,
  97. duration : number,
  98. delay : number,
  99. timingFunction : (t : number) => number,
  100. template : (v : number) => void) {
  101. this.startValue = startValue;
  102. this.endValue = endValue;
  103. this.duration = duration;
  104. this.timingFunction = timingFunction;
  105. this.delay = delay;
  106. this.template = template;
  107. }
  108. run(time : number) {
  109. let range = this.endValue - this.startValue;
  110. let progress = time / this.duration
  111. if(progress != 1) progress = this.timingFunction(progress)
  112. this.template(this.startValue + range * progress)
  113. }
  114. }