progressFoundation.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import BaseFoundation, { DefaultAdapter } from '../base/foundation';
  2. export interface MarkerListItem {
  3. start: number;
  4. end: number;
  5. title: string;
  6. width: string;
  7. left: string
  8. }
  9. export interface Marker {
  10. start: number;
  11. title: string
  12. }
  13. export interface VideoProgressAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
  14. getSliderRef: () => HTMLDivElement | null;
  15. getMarkersList: () => MarkerListItem[];
  16. setIsDragging: (isDragging: boolean) => void;
  17. setIsHandleHovering: (isHandleHovering: boolean) => void;
  18. setActiveIndex: (activeIndex: number) => void;
  19. setMovingInfo: (movingInfo: { progress: number; offset: number; value: number } | null) => void
  20. }
  21. export default class VideoProgressFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<VideoProgressAdapter<P, S>, P, S> {
  22. constructor(adapter: VideoProgressAdapter<P, S>) {
  23. super({ ...adapter });
  24. }
  25. handleDocumentMouseMove = (e: MouseEvent) => {
  26. const { isDragging } = this.getStates();
  27. if (isDragging) {
  28. this.handleMouseEvent(e, true);
  29. }
  30. };
  31. handleDocumentMouseUp = () => {
  32. const { isDragging } = this.getStates();
  33. if (isDragging) {
  34. this._adapter.setIsDragging(false);
  35. }
  36. document.removeEventListener('mousemove', this.handleDocumentMouseMove);
  37. document.removeEventListener('mouseup', this.handleDocumentMouseUp);
  38. };
  39. handleMouseDown = (e: any) => {
  40. this._adapter.setIsDragging(true);
  41. this.handleMouseEvent(e, true);
  42. document.addEventListener('mousemove', this.handleDocumentMouseMove);
  43. document.addEventListener('mouseup', this.handleDocumentMouseUp);
  44. };
  45. handleMouseUp = () => {
  46. const { isDragging } = this.getStates();
  47. if (isDragging) {
  48. this._adapter.setIsDragging(false);
  49. }
  50. };
  51. handleMouseEvent = (e: any, shouldSetValue: boolean = true) => {
  52. const { isDragging } = this.getStates();
  53. const { onChange, max } = this.getProps();
  54. const sliderRef = this._adapter.getSliderRef();
  55. if (!sliderRef) return;
  56. const rect = sliderRef.getBoundingClientRect();
  57. const offset = (e.clientX - rect.left);
  58. const total = rect.width;
  59. const percentage = Math.min(Math.max(offset / total, 0), 1);
  60. const value = percentage * max;
  61. if (shouldSetValue && (isDragging || e.type === 'mousedown')) {
  62. this.setActiveIndex(value);
  63. onChange(value);
  64. }
  65. this._adapter.setMovingInfo({
  66. progress: percentage,
  67. offset: offset - rect.width / 2,
  68. value
  69. });
  70. };
  71. handleSliderMouseEnter = (index: number) => {
  72. const { value: currentValue } = this.getProps();
  73. const markersList = this._adapter.getMarkersList();
  74. const currentSlider = markersList[index];
  75. if (currentSlider.start < currentValue && currentSlider.end > currentValue) {
  76. this._adapter.setIsHandleHovering(true);
  77. } else {
  78. this._adapter.setIsHandleHovering(false);
  79. }
  80. }
  81. handleSliderMouseLeave = (index: number) => {
  82. const { value: currentValue } = this.getProps();
  83. const markersList = this._adapter.getMarkersList();
  84. const currentSlider = markersList[index];
  85. if (currentSlider.start < currentValue && currentSlider.end > currentValue) {
  86. this._adapter.setIsHandleHovering(false);
  87. }
  88. }
  89. setActiveIndex = (currentValue: number) => {
  90. const markersList = this._adapter.getMarkersList();
  91. markersList.map((marker: MarkerListItem, index: number) => {
  92. if (currentValue < marker.end && currentValue > marker.start) {
  93. this._adapter.setIsHandleHovering(true);
  94. this._adapter.setActiveIndex(index);
  95. }
  96. });
  97. }
  98. getValueWidth = (marker: MarkerListItem, value: number) => {
  99. const { start, end } = marker;
  100. if (value > end) {
  101. return 'calc(100% - 2px)';
  102. } else if (value < start) {
  103. return '0%';
  104. } else {
  105. return `${(value - start) / (end - start) * 100}%`;
  106. }
  107. }
  108. // Get the width of the video being played
  109. getPlayedWidth = (marker: MarkerListItem) => {
  110. const { value: currentValue } = this.getProps();
  111. return this.getValueWidth(marker, currentValue);
  112. }
  113. getLoadedWidth = (marker: MarkerListItem) => {
  114. const { bufferedValue } = this.getProps();
  115. return this.getValueWidth(marker, bufferedValue);
  116. }
  117. }