uvue.uts 3.0 KB

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