Tween.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import EASINGS from './Easings'
  2. export default class Tween {
  3. static activeTweens: Tween[] = []
  4. static idCounter: number = 0
  5. static listeners: Map<number, Function[]> = new Map<number, Function[]>()
  6. id: number
  7. obj: any
  8. objStart: any
  9. objTarget: any
  10. startTime: number
  11. endTime: number
  12. easing: Function
  13. completedCallback: Function
  14. static create(obj, targetProperties, duration, easing = EASINGS.Linear.EaseNone, completedCallback = () => { }) {
  15. let singleTween = new Tween();
  16. singleTween.id = ++Tween.idCounter;
  17. singleTween.obj = obj;
  18. singleTween.objStart = {};
  19. singleTween.objTarget = targetProperties;
  20. Tween.saveProperties(singleTween.objStart, obj, targetProperties);
  21. singleTween.startTime = new Date().getTime();
  22. singleTween.endTime = singleTween.startTime + duration;
  23. singleTween.easing = easing;
  24. singleTween.completedCallback = completedCallback;
  25. Tween.activeTweens.push(singleTween);
  26. return singleTween.id;
  27. }
  28. static cancel(tweenId): Tween | undefined {
  29. let tween = Tween.activeTweens.find(tween => tweenId == tween.id);
  30. if (tween) {
  31. let index = Tween.activeTweens.indexOf(tween);
  32. Tween.activeTweens.splice(index, 1);
  33. return tween;
  34. }
  35. return
  36. };
  37. static stop(tweenId) {
  38. let tween = Tween.cancel(tweenId);
  39. tween?.completedCallback();
  40. return tween;
  41. };
  42. static saveProperties(singleTweenStart, obj, targetProperties) {
  43. for (let property in targetProperties) {
  44. let startValue = obj[property];
  45. if (typeof startValue == "object") {
  46. singleTweenStart[property] = {};
  47. Tween.saveProperties(singleTweenStart[property], obj[property], targetProperties[property]);
  48. continue;
  49. }
  50. singleTweenStart[property] = startValue;
  51. }
  52. }
  53. static update() {
  54. let completed: Tween[] = [];
  55. for (let i = 0; i < Tween.activeTweens.length; i++) {
  56. let singleTween = Tween.activeTweens[i];
  57. if (Tween.updateSingleTween(singleTween) == 1) {
  58. completed.push(singleTween);
  59. }
  60. }
  61. for (let i = 0; i < completed.length; i++) {
  62. let singleTween = completed[i];
  63. singleTween.completedCallback();
  64. let foundIndex = Tween.activeTweens.indexOf(singleTween);
  65. if (foundIndex != -1) {
  66. Tween.activeTweens.splice(foundIndex, 1);
  67. }
  68. }
  69. for (let i = 0; i < completed.length; i++) {
  70. this.listeners[completed[i].id] = []
  71. }
  72. };
  73. static subscribeToTween(tweenId, handler) {
  74. this.listeners[tweenId].push(handler)
  75. }
  76. static updateSingleTween(singleTween) {
  77. let currentTime = new Date().getTime();
  78. let runTime = currentTime - singleTween.startTime;
  79. let duration = singleTween.endTime - singleTween.startTime;
  80. let percentageComplete = Math.min(1, runTime / duration);
  81. let valueToUpdate = singleTween.easing(percentageComplete);
  82. Tween.updateProperties(singleTween.obj, singleTween.objStart, singleTween.objTarget, valueToUpdate);
  83. return percentageComplete;
  84. }
  85. static updateProperties(obj, objStart, objTarget, valueToUpdate) {
  86. for (let property in objStart) {
  87. let startValue = objStart[property];
  88. if (typeof startValue == "object") {
  89. Tween.updateProperties(obj[property], objStart[property], objTarget[property], valueToUpdate);
  90. continue;
  91. }
  92. let endValue = objTarget[property];
  93. let delta = endValue - startValue;
  94. obj[property] = startValue + (delta * valueToUpdate);
  95. }
  96. };
  97. };