a4d29da91ff762fc9f6b43323db1c8340a43f8c7e987795c9e6a25cf37de85db216f76a0d32668e10657edb131a0f2e87160d130e4e7f5988c51a51c27c949 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import {requestAnimationFrame, cancelAnimationFrame} from './../helpers/feature';
  2. /**
  3. * @class Interval
  4. * @util
  5. */
  6. class Interval {
  7. static create(func, delay) {
  8. return new Interval(func, delay);
  9. }
  10. constructor(func, delay) {
  11. /**
  12. * Animation frame request id.
  13. *
  14. * @type {Number}
  15. */
  16. this.timer = null;
  17. /**
  18. * Function to invoke repeatedly.
  19. *
  20. * @type {Function}
  21. */
  22. this.func = func;
  23. /**
  24. * Number of milliseconds that function should wait before next call.
  25. */
  26. this.delay = parseDelay(delay);
  27. /**
  28. * Flag which indicates if interval object was stopped.
  29. *
  30. * @type {Boolean}
  31. * @default true
  32. */
  33. this.stopped = true;
  34. /**
  35. * Interval time (in milliseconds) of the last callback call.
  36. *
  37. * @private
  38. * @type {Number}
  39. */
  40. this._then = null;
  41. /**
  42. * Bounded function `func`.
  43. *
  44. * @private
  45. * @type {Function}
  46. */
  47. this._callback = () => this.__callback();
  48. }
  49. /**
  50. * Start loop.
  51. *
  52. * @returns {Interval}
  53. */
  54. start() {
  55. if (this.stopped) {
  56. this._then = Date.now();
  57. this.stopped = false;
  58. this.timer = requestAnimationFrame(this._callback);
  59. }
  60. return this;
  61. }
  62. /**
  63. * Stop looping.
  64. *
  65. * @returns {Interval}
  66. */
  67. stop() {
  68. if (!this.stopped) {
  69. this.stopped = true;
  70. cancelAnimationFrame(this.timer);
  71. this.timer = null;
  72. }
  73. return this;
  74. }
  75. /**
  76. * Loop callback, fired on every animation frame.
  77. *
  78. * @private
  79. */
  80. __callback() {
  81. this.timer = requestAnimationFrame(this._callback);
  82. if (this.delay) {
  83. const now = Date.now();
  84. const elapsed = now - this._then;
  85. if (elapsed > this.delay) {
  86. this._then = now - (elapsed % this.delay);
  87. this.func();
  88. }
  89. } else {
  90. this.func();
  91. }
  92. }
  93. }
  94. export default Interval;
  95. export function parseDelay(delay) {
  96. if (typeof delay === 'string' && /fps$/.test(delay)) {
  97. delay = 1000 / parseInt(delay.replace('fps', '') || 0, 10);
  98. }
  99. return delay;
  100. }