@douyinfe/semi-foundation 2.79.0 → 2.80.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cascader/foundation.ts +2 -2
- package/lib/cjs/cascader/foundation.js +1 -1
- package/lib/cjs/tooltip/foundation.js +4 -1
- package/lib/cjs/tree/treeUtil.d.ts +1 -1
- package/lib/cjs/videoPlayer/animation.scss +7 -0
- package/lib/cjs/videoPlayer/constants.d.ts +30 -0
- package/lib/cjs/videoPlayer/constants.js +48 -0
- package/lib/cjs/videoPlayer/foundation.d.ts +75 -0
- package/lib/cjs/videoPlayer/foundation.js +291 -0
- package/lib/cjs/videoPlayer/progressFoundation.d.ts +38 -0
- package/lib/cjs/videoPlayer/progressFoundation.js +131 -0
- package/lib/cjs/videoPlayer/variables.scss +75 -0
- package/lib/cjs/videoPlayer/videoPlayer.css +279 -0
- package/lib/cjs/videoPlayer/videoPlayer.scss +323 -0
- package/lib/es/cascader/foundation.js +1 -1
- package/lib/es/tooltip/foundation.js +4 -1
- package/lib/es/tree/treeUtil.d.ts +1 -1
- package/lib/es/videoPlayer/animation.scss +7 -0
- package/lib/es/videoPlayer/constants.d.ts +30 -0
- package/lib/es/videoPlayer/constants.js +43 -0
- package/lib/es/videoPlayer/foundation.d.ts +75 -0
- package/lib/es/videoPlayer/foundation.js +283 -0
- package/lib/es/videoPlayer/progressFoundation.d.ts +38 -0
- package/lib/es/videoPlayer/progressFoundation.js +123 -0
- package/lib/es/videoPlayer/variables.scss +75 -0
- package/lib/es/videoPlayer/videoPlayer.css +279 -0
- package/lib/es/videoPlayer/videoPlayer.scss +323 -0
- package/package.json +4 -4
- package/tooltip/foundation.ts +4 -1
- package/videoPlayer/animation.scss +7 -0
- package/videoPlayer/constants.ts +39 -0
- package/videoPlayer/foundation.ts +332 -0
- package/videoPlayer/progressFoundation.ts +136 -0
- package/videoPlayer/variables.scss +75 -0
- package/videoPlayer/videoPlayer.scss +323 -0
|
@@ -57,6 +57,7 @@ export default class Tooltip extends BaseFoundation {
|
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
this.show = () => {
|
|
60
|
+
this._initContainerPosition();
|
|
60
61
|
if (this._adapter.getAnimatingState()) {
|
|
61
62
|
return;
|
|
62
63
|
}
|
|
@@ -226,7 +227,6 @@ export default class Tooltip extends BaseFoundation {
|
|
|
226
227
|
this._mounted = true;
|
|
227
228
|
this._bindEvent();
|
|
228
229
|
this._shouldShow();
|
|
229
|
-
this._initContainerPosition();
|
|
230
230
|
if (!wrapperId) {
|
|
231
231
|
this._adapter.setId();
|
|
232
232
|
}
|
|
@@ -1034,6 +1034,9 @@ export default class Tooltip extends BaseFoundation {
|
|
|
1034
1034
|
this._adapter.unregisterScrollHandler();
|
|
1035
1035
|
}
|
|
1036
1036
|
_initContainerPosition() {
|
|
1037
|
+
if (this._adapter.getContainerPosition() || !this._adapter.containerIsBody()) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1037
1040
|
this._adapter.updateContainerPosition();
|
|
1038
1041
|
}
|
|
1039
1042
|
_handleTriggerKeydown(event) {
|
|
@@ -83,6 +83,6 @@ export declare function getValueOrKey(data: any, keyMaps?: KeyMapProps): any;
|
|
|
83
83
|
export declare function normalizeValue(value: any, withObject: boolean, keyMaps?: KeyMapProps): any;
|
|
84
84
|
export declare function updateKeys(keySet: Set<string> | string[], keyEntities: KeyEntities): string[];
|
|
85
85
|
export declare function calcDisabledKeys(keyEntities: KeyEntities, keyMaps?: KeyMapProps): Set<string>;
|
|
86
|
-
export declare function calcDropRelativePosition(event: any, treeNode: any):
|
|
86
|
+
export declare function calcDropRelativePosition(event: any, treeNode: any): 0 | 1 | -1;
|
|
87
87
|
export declare function getDragNodesKeys(key: string, keyEntities: KeyEntities): string[];
|
|
88
88
|
export declare function calcDropActualPosition(pos: string, relativeDropPos: any): any;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
$animation_duration-videoPlayer_controls-show: 500ms; // videoPlayer菜单栏-弹出动画-动画持续时间
|
|
2
|
+
$animation_duration-videoPlayer_slider-in: 300ms; // videoPlayer进度条-弹出动画-动画持续时间
|
|
3
|
+
$animation_duration-videoPlayer_slider-out: 300ms; // videoPlayer进度条-收起动画-动画持续时间
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
$animation_function-videoPlayer_slider-in: cubic-bezier(0.62, 0.05, 0.36, 0.95); // videoPlayer进度条-弹出动画-动画插值函数
|
|
7
|
+
$animation_function-videoPlayer_slider-out: cubic-bezier(0.62, 0.05, 0.36, 0.95); // videoPlayer进度条-收起动画-动画插值函数
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
declare const cssClasses: {
|
|
2
|
+
readonly PREFIX: "semi-videoPlayer";
|
|
3
|
+
readonly PREFIX_CONTROLS: "semi-videoPlayer-controls";
|
|
4
|
+
readonly PREFIX_PROGRESS: "semi-videoPlayer-progress";
|
|
5
|
+
};
|
|
6
|
+
declare const strings: {
|
|
7
|
+
readonly DARK: "dark";
|
|
8
|
+
readonly LIGHT: "light";
|
|
9
|
+
readonly PLAY: "play";
|
|
10
|
+
readonly NEXT: "next";
|
|
11
|
+
readonly TIME: "time";
|
|
12
|
+
readonly VOLUME: "volume";
|
|
13
|
+
readonly PLAYBACK_RATE: "playbackRate";
|
|
14
|
+
readonly QUALITY: "quality";
|
|
15
|
+
readonly ROUTE: "route";
|
|
16
|
+
readonly MIRROR: "mirror";
|
|
17
|
+
readonly FULLSCREEN: "fullscreen";
|
|
18
|
+
readonly PICTURE_IN_PICTURE: "pictureInPicture";
|
|
19
|
+
};
|
|
20
|
+
declare const numbers: {
|
|
21
|
+
readonly DEFAULT_VOLUME: 100;
|
|
22
|
+
readonly DEFAULT_SEEK_TIME: 10;
|
|
23
|
+
readonly DEFAULT_VOLUME_STEP: 10;
|
|
24
|
+
readonly DEFAULT_PLAYBACK_RATE: 1;
|
|
25
|
+
};
|
|
26
|
+
declare const DEFAULT_PLAYBACK_RATE: {
|
|
27
|
+
label: string;
|
|
28
|
+
value: number;
|
|
29
|
+
}[];
|
|
30
|
+
export { cssClasses, strings, numbers, DEFAULT_PLAYBACK_RATE };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BASE_CLASS_PREFIX } from '../base/constants';
|
|
2
|
+
const cssClasses = {
|
|
3
|
+
PREFIX: `${BASE_CLASS_PREFIX}-videoPlayer`,
|
|
4
|
+
PREFIX_CONTROLS: `${BASE_CLASS_PREFIX}-videoPlayer-controls`,
|
|
5
|
+
PREFIX_PROGRESS: `${BASE_CLASS_PREFIX}-videoPlayer-progress`
|
|
6
|
+
};
|
|
7
|
+
const strings = {
|
|
8
|
+
DARK: 'dark',
|
|
9
|
+
LIGHT: 'light',
|
|
10
|
+
PLAY: 'play',
|
|
11
|
+
NEXT: 'next',
|
|
12
|
+
TIME: 'time',
|
|
13
|
+
VOLUME: 'volume',
|
|
14
|
+
PLAYBACK_RATE: 'playbackRate',
|
|
15
|
+
QUALITY: 'quality',
|
|
16
|
+
ROUTE: 'route',
|
|
17
|
+
MIRROR: 'mirror',
|
|
18
|
+
FULLSCREEN: 'fullscreen',
|
|
19
|
+
PICTURE_IN_PICTURE: 'pictureInPicture'
|
|
20
|
+
};
|
|
21
|
+
const numbers = {
|
|
22
|
+
DEFAULT_VOLUME: 100,
|
|
23
|
+
DEFAULT_SEEK_TIME: 10,
|
|
24
|
+
DEFAULT_VOLUME_STEP: 10,
|
|
25
|
+
DEFAULT_PLAYBACK_RATE: 1
|
|
26
|
+
};
|
|
27
|
+
const DEFAULT_PLAYBACK_RATE = [{
|
|
28
|
+
label: '2.0x',
|
|
29
|
+
value: 2
|
|
30
|
+
}, {
|
|
31
|
+
label: '1.5x',
|
|
32
|
+
value: 1.5
|
|
33
|
+
}, {
|
|
34
|
+
label: '1.25x',
|
|
35
|
+
value: 1.25
|
|
36
|
+
}, {
|
|
37
|
+
label: '1.0x',
|
|
38
|
+
value: 1
|
|
39
|
+
}, {
|
|
40
|
+
label: '0.75x',
|
|
41
|
+
value: 0.75
|
|
42
|
+
}];
|
|
43
|
+
export { cssClasses, strings, numbers, DEFAULT_PLAYBACK_RATE };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/// <reference types="lodash" />
|
|
2
|
+
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
3
|
+
export interface VideoPlayerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
|
|
4
|
+
getVideo: () => HTMLVideoElement | null;
|
|
5
|
+
getVideoWrapper: () => HTMLDivElement | null;
|
|
6
|
+
notifyPause: () => void;
|
|
7
|
+
notifyPlay: () => void;
|
|
8
|
+
notifyQualityChange: (quality: string) => void;
|
|
9
|
+
notifyRateChange: (rate: number) => void;
|
|
10
|
+
notifyRouteChange: (route: string) => void;
|
|
11
|
+
notifyVolumeChange: (volume: number) => void;
|
|
12
|
+
setBufferedValue: (bufferedValue: number) => void;
|
|
13
|
+
setCurrentTime: (currentTime: number) => void;
|
|
14
|
+
setIsError: (isError: boolean) => void;
|
|
15
|
+
setIsMirror: (isMirror: boolean) => void;
|
|
16
|
+
setIsPlaying: (isPlaying: boolean) => void;
|
|
17
|
+
setMuted: (muted: boolean) => void;
|
|
18
|
+
setNotificationContent: (content: string) => void;
|
|
19
|
+
setPlaybackRate: (rate: number) => void;
|
|
20
|
+
setQuality: (quality: string) => void;
|
|
21
|
+
setRoute: (route: string) => void;
|
|
22
|
+
setShowControls: (showControls: boolean) => void;
|
|
23
|
+
setShowNotification: (showNotification: boolean) => void;
|
|
24
|
+
setTotalTime: (totalTime: number) => void;
|
|
25
|
+
setVolume: (volume: number) => void;
|
|
26
|
+
}
|
|
27
|
+
export default class VideoPlayerFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<VideoPlayerAdapter<P, S>, P, S> {
|
|
28
|
+
constructor(adapter: VideoPlayerAdapter<P, S>);
|
|
29
|
+
private controlsTimer;
|
|
30
|
+
private scrollPosition;
|
|
31
|
+
init(): void;
|
|
32
|
+
destroy(): void;
|
|
33
|
+
shouldShowControlItem(name: string): boolean;
|
|
34
|
+
clearTimer(): void;
|
|
35
|
+
handleMouseMove: import("lodash").DebouncedFuncLeading<() => void>;
|
|
36
|
+
handleTimeChange(value: number): void;
|
|
37
|
+
handleTimeUpdate(): void;
|
|
38
|
+
handleDurationChange(): void;
|
|
39
|
+
handleError(): void;
|
|
40
|
+
handlePlayOrPause(): void;
|
|
41
|
+
handlePlay(): void;
|
|
42
|
+
handlePause(): void;
|
|
43
|
+
handleCanPlay: () => void;
|
|
44
|
+
handleWaiting: (locale: any) => void;
|
|
45
|
+
handleStalled: (locale: any) => void;
|
|
46
|
+
handleProgress: () => void;
|
|
47
|
+
handleEnded: () => void;
|
|
48
|
+
handleVolumeChange(value: number): void;
|
|
49
|
+
handleVolumeSilent: () => void;
|
|
50
|
+
checkFullScreen(): boolean;
|
|
51
|
+
handleFullscreen: () => void;
|
|
52
|
+
handleRateChange(rate: {
|
|
53
|
+
label: string;
|
|
54
|
+
value: number;
|
|
55
|
+
}, locale: any): void;
|
|
56
|
+
handleQualityChange(quality: {
|
|
57
|
+
label: string;
|
|
58
|
+
value: string;
|
|
59
|
+
}, locale: any): void;
|
|
60
|
+
handleRouteChange(route: {
|
|
61
|
+
label: string;
|
|
62
|
+
value: string;
|
|
63
|
+
}, locale: any): void;
|
|
64
|
+
handleMirror: (locale: any) => void;
|
|
65
|
+
handlePictureInPicture: () => void;
|
|
66
|
+
handleLeavePictureInPicture: () => void;
|
|
67
|
+
handleTemporaryNotification: (content: string) => void;
|
|
68
|
+
restorePlayPosition(): void;
|
|
69
|
+
handleMouseEnterWrapper: () => void;
|
|
70
|
+
handleMouseLeaveWrapper: () => void;
|
|
71
|
+
handleFullscreenChange: () => void;
|
|
72
|
+
registerEvent: () => void;
|
|
73
|
+
unregisterEvent: () => void;
|
|
74
|
+
handleBodyKeyDown(e: KeyboardEvent): void;
|
|
75
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import _throttle from "lodash/throttle";
|
|
2
|
+
import BaseFoundation from '../base/foundation';
|
|
3
|
+
export default class VideoPlayerFoundation extends BaseFoundation {
|
|
4
|
+
constructor(adapter) {
|
|
5
|
+
super(Object.assign({}, adapter));
|
|
6
|
+
this.scrollPosition = null;
|
|
7
|
+
this.handleMouseMove = _throttle(() => {
|
|
8
|
+
this._adapter.setShowControls(true);
|
|
9
|
+
this.clearTimer();
|
|
10
|
+
this.controlsTimer = setTimeout(() => {
|
|
11
|
+
this._adapter.setShowControls(false);
|
|
12
|
+
}, 3000);
|
|
13
|
+
}, 200);
|
|
14
|
+
this.handleCanPlay = () => {
|
|
15
|
+
this._adapter.setShowNotification(false);
|
|
16
|
+
};
|
|
17
|
+
this.handleWaiting = locale => {
|
|
18
|
+
this._adapter.setNotificationContent(locale.loading);
|
|
19
|
+
this._adapter.setShowNotification(true);
|
|
20
|
+
};
|
|
21
|
+
this.handleStalled = locale => {
|
|
22
|
+
this._adapter.setNotificationContent(locale.stall);
|
|
23
|
+
this._adapter.setShowNotification(true);
|
|
24
|
+
};
|
|
25
|
+
this.handleProgress = () => {
|
|
26
|
+
const video = this._adapter.getVideo();
|
|
27
|
+
if (video && video.buffered.length > 0) {
|
|
28
|
+
const bufferedEnd = video.buffered.end(video.buffered.length - 1);
|
|
29
|
+
this._adapter.setBufferedValue(bufferedEnd);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
this.handleEnded = () => {
|
|
33
|
+
this._adapter.setIsPlaying(false);
|
|
34
|
+
this._adapter.setShowControls(true);
|
|
35
|
+
};
|
|
36
|
+
this.handleVolumeSilent = () => {
|
|
37
|
+
const video = this._adapter.getVideo();
|
|
38
|
+
const {
|
|
39
|
+
volume,
|
|
40
|
+
muted
|
|
41
|
+
} = this.getStates();
|
|
42
|
+
if (!video) return;
|
|
43
|
+
if (muted) {
|
|
44
|
+
video.volume = volume / 100;
|
|
45
|
+
this._adapter.setVolume(volume);
|
|
46
|
+
this._adapter.setMuted(false);
|
|
47
|
+
} else {
|
|
48
|
+
video.volume = 0;
|
|
49
|
+
this._adapter.setMuted(true);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
this.handleFullscreen = () => {
|
|
53
|
+
const videoWrapper = this._adapter.getVideoWrapper();
|
|
54
|
+
const isFullScreen = this.checkFullScreen();
|
|
55
|
+
if (videoWrapper) {
|
|
56
|
+
if (isFullScreen) {
|
|
57
|
+
document.exitFullscreen();
|
|
58
|
+
} else {
|
|
59
|
+
// record scroll position before entering fullscreen
|
|
60
|
+
this.scrollPosition = {
|
|
61
|
+
x: window.scrollX,
|
|
62
|
+
y: window.scrollY
|
|
63
|
+
};
|
|
64
|
+
videoWrapper.requestFullscreen();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
this.handleMirror = locale => {
|
|
69
|
+
const {
|
|
70
|
+
isMirror
|
|
71
|
+
} = this.getStates();
|
|
72
|
+
this._adapter.setIsMirror(!isMirror);
|
|
73
|
+
this.handleTemporaryNotification(!isMirror ? locale.mirror : locale.cancelMirror);
|
|
74
|
+
};
|
|
75
|
+
this.handlePictureInPicture = () => {
|
|
76
|
+
const video = this._adapter.getVideo();
|
|
77
|
+
if (!video) return;
|
|
78
|
+
video.requestPictureInPicture();
|
|
79
|
+
};
|
|
80
|
+
this.handleLeavePictureInPicture = () => {
|
|
81
|
+
const video = this._adapter.getVideo();
|
|
82
|
+
if (!video) return;
|
|
83
|
+
this._adapter.setIsPlaying(!video.paused);
|
|
84
|
+
};
|
|
85
|
+
this.handleTemporaryNotification = content => {
|
|
86
|
+
this._adapter.setNotificationContent(content);
|
|
87
|
+
this._adapter.setShowNotification(true);
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
this._adapter.setShowNotification(false);
|
|
90
|
+
}, 1000);
|
|
91
|
+
};
|
|
92
|
+
this.handleMouseEnterWrapper = () => {
|
|
93
|
+
this._adapter.setShowControls(true);
|
|
94
|
+
};
|
|
95
|
+
this.handleMouseLeaveWrapper = () => {
|
|
96
|
+
const {
|
|
97
|
+
isPlaying
|
|
98
|
+
} = this.getStates();
|
|
99
|
+
if (isPlaying) {
|
|
100
|
+
this._adapter.setShowControls(false);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
this.handleFullscreenChange = () => {
|
|
104
|
+
const isFullScreen = this.checkFullScreen();
|
|
105
|
+
if (isFullScreen) {
|
|
106
|
+
document.addEventListener('mousemove', this.handleMouseMove);
|
|
107
|
+
} else {
|
|
108
|
+
// according to the exit fullScreen has two way, Esc && click the button
|
|
109
|
+
// so we need to restore scroll position after exiting fullscreen
|
|
110
|
+
if (this.scrollPosition) {
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);
|
|
113
|
+
this.scrollPosition = null;
|
|
114
|
+
}, 0);
|
|
115
|
+
}
|
|
116
|
+
document.removeEventListener('mousemove', this.handleMouseMove);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
this.registerEvent = () => {
|
|
120
|
+
const video = this._adapter.getVideo();
|
|
121
|
+
if (!video) return;
|
|
122
|
+
document.addEventListener('keydown', e => this.handleBodyKeyDown(e));
|
|
123
|
+
document.addEventListener('fullscreenchange', this.handleFullscreenChange);
|
|
124
|
+
video.addEventListener('leavepictureinpicture', this.handleLeavePictureInPicture);
|
|
125
|
+
};
|
|
126
|
+
this.unregisterEvent = () => {
|
|
127
|
+
const video = this._adapter.getVideo();
|
|
128
|
+
if (!video) return;
|
|
129
|
+
document.removeEventListener('keydown', e => this.handleBodyKeyDown(e));
|
|
130
|
+
document.removeEventListener('fullscreenchange', this.handleFullscreenChange);
|
|
131
|
+
video.removeEventListener('leavepictureinpicture', this.handleLeavePictureInPicture);
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
init() {
|
|
135
|
+
const {
|
|
136
|
+
volume,
|
|
137
|
+
muted
|
|
138
|
+
} = this.getProps();
|
|
139
|
+
const video = this._adapter.getVideo();
|
|
140
|
+
if (video) {
|
|
141
|
+
this._adapter.setTotalTime(video.duration);
|
|
142
|
+
this.handleVolumeChange(muted ? 0 : volume);
|
|
143
|
+
}
|
|
144
|
+
this.registerEvent();
|
|
145
|
+
}
|
|
146
|
+
destroy() {
|
|
147
|
+
this.unregisterEvent();
|
|
148
|
+
this.clearTimer();
|
|
149
|
+
}
|
|
150
|
+
shouldShowControlItem(name) {
|
|
151
|
+
const {
|
|
152
|
+
controlsList
|
|
153
|
+
} = this.getProps();
|
|
154
|
+
if (controlsList.includes(name)) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
clearTimer() {
|
|
160
|
+
if (this.controlsTimer) {
|
|
161
|
+
clearTimeout(this.controlsTimer);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
handleTimeChange(value) {
|
|
165
|
+
const video = this._adapter.getVideo();
|
|
166
|
+
if (!video) return;
|
|
167
|
+
if (!Number.isNaN(value)) {
|
|
168
|
+
video.currentTime = value;
|
|
169
|
+
this._adapter.setCurrentTime(value);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
handleTimeUpdate() {
|
|
173
|
+
const video = this._adapter.getVideo();
|
|
174
|
+
if (!video) return;
|
|
175
|
+
this._adapter.setCurrentTime(video.currentTime);
|
|
176
|
+
}
|
|
177
|
+
handleDurationChange() {
|
|
178
|
+
const video = this._adapter.getVideo();
|
|
179
|
+
if (!video) return;
|
|
180
|
+
this._adapter.setTotalTime(video.duration);
|
|
181
|
+
}
|
|
182
|
+
handleError() {
|
|
183
|
+
this._adapter.setIsError(true);
|
|
184
|
+
}
|
|
185
|
+
handlePlayOrPause() {
|
|
186
|
+
const video = this._adapter.getVideo();
|
|
187
|
+
if (!video) return;
|
|
188
|
+
video.paused ? this.handlePlay() : this.handlePause();
|
|
189
|
+
}
|
|
190
|
+
handlePlay() {
|
|
191
|
+
const video = this._adapter.getVideo();
|
|
192
|
+
if (video) {
|
|
193
|
+
video.play();
|
|
194
|
+
this._adapter.setIsPlaying(true);
|
|
195
|
+
this._adapter.notifyPlay();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
handlePause() {
|
|
199
|
+
const video = this._adapter.getVideo();
|
|
200
|
+
if (video) {
|
|
201
|
+
video.pause();
|
|
202
|
+
this._adapter.setIsPlaying(false);
|
|
203
|
+
this._adapter.notifyPause();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
handleVolumeChange(value) {
|
|
207
|
+
const video = this._adapter.getVideo();
|
|
208
|
+
if (!video) return;
|
|
209
|
+
const volume = Math.floor(value > 0 ? value : 0);
|
|
210
|
+
video.volume = volume / 100;
|
|
211
|
+
this._adapter.setVolume(volume);
|
|
212
|
+
this._adapter.setMuted(volume === 0 ? true : false);
|
|
213
|
+
}
|
|
214
|
+
checkFullScreen() {
|
|
215
|
+
const videoWrapper = this._adapter.getVideoWrapper();
|
|
216
|
+
if (!videoWrapper) return false;
|
|
217
|
+
return !!(document.fullscreenElement === videoWrapper ||
|
|
218
|
+
// @ts-ignore
|
|
219
|
+
(document === null || document === void 0 ? void 0 : document.webkitFullscreenElement) === videoWrapper ||
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
(document === null || document === void 0 ? void 0 : document.mozFullScreenElement) === videoWrapper ||
|
|
222
|
+
// @ts-ignore
|
|
223
|
+
(document === null || document === void 0 ? void 0 : document.msFullscreenElement) === videoWrapper || (
|
|
224
|
+
// @ts-ignore
|
|
225
|
+
videoWrapper === null || videoWrapper === void 0 ? void 0 : videoWrapper.webkitDisplayingFullscreen) // iOS Safari 特殊处理
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
handleRateChange(rate, locale) {
|
|
229
|
+
const video = this._adapter.getVideo();
|
|
230
|
+
if (!video) return;
|
|
231
|
+
video.playbackRate = rate.value;
|
|
232
|
+
this._adapter.setPlaybackRate(rate.value);
|
|
233
|
+
this._adapter.notifyRateChange(rate.value);
|
|
234
|
+
this.handleTemporaryNotification(locale.rateChange.replace('${rate}', rate.label));
|
|
235
|
+
}
|
|
236
|
+
handleQualityChange(quality, locale) {
|
|
237
|
+
this._adapter.setQuality(quality.value);
|
|
238
|
+
this._adapter.notifyQualityChange(quality.value);
|
|
239
|
+
this.handleTemporaryNotification(locale.qualityChange.replace('${quality}', quality.label));
|
|
240
|
+
this.restorePlayPosition();
|
|
241
|
+
}
|
|
242
|
+
handleRouteChange(route, locale) {
|
|
243
|
+
var _a, _b;
|
|
244
|
+
this._adapter.setRoute(route.value);
|
|
245
|
+
(_b = (_a = this._adapter).notifyRouteChange) === null || _b === void 0 ? void 0 : _b.call(_a, route.value);
|
|
246
|
+
this.handleTemporaryNotification(locale.routeChange.replace('${route}', route.label));
|
|
247
|
+
this.restorePlayPosition();
|
|
248
|
+
}
|
|
249
|
+
restorePlayPosition() {
|
|
250
|
+
const video = this._adapter.getVideo();
|
|
251
|
+
if (!video) return;
|
|
252
|
+
const wasPlaying = !video.paused;
|
|
253
|
+
const currentTime = video.currentTime;
|
|
254
|
+
const handleLoaded = () => {
|
|
255
|
+
video.currentTime = currentTime;
|
|
256
|
+
if (wasPlaying) {
|
|
257
|
+
video.play();
|
|
258
|
+
}
|
|
259
|
+
video.removeEventListener('loadeddata', handleLoaded);
|
|
260
|
+
};
|
|
261
|
+
video.addEventListener('loadeddata', handleLoaded);
|
|
262
|
+
}
|
|
263
|
+
handleBodyKeyDown(e) {
|
|
264
|
+
const {
|
|
265
|
+
currentTime,
|
|
266
|
+
volume
|
|
267
|
+
} = this.getStates();
|
|
268
|
+
const {
|
|
269
|
+
seekTime
|
|
270
|
+
} = this.getProps();
|
|
271
|
+
if (e.key === ' ') {
|
|
272
|
+
this.handlePlayOrPause();
|
|
273
|
+
// } else if (e.key === 'ArrowUp') {
|
|
274
|
+
// this.handleVolumeChange(volume + numbers.DEFAULT_VOLUME_STEP);
|
|
275
|
+
// } else if (e.key === 'ArrowDown') {
|
|
276
|
+
// this.handleVolumeChange(volume - numbers.DEFAULT_VOLUME_STEP);
|
|
277
|
+
} else if (e.key === 'ArrowLeft') {
|
|
278
|
+
this.handleTimeChange(currentTime - seekTime);
|
|
279
|
+
} else if (e.key === 'ArrowRight') {
|
|
280
|
+
this.handleTimeChange(currentTime + seekTime);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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: {
|
|
20
|
+
progress: number;
|
|
21
|
+
offset: number;
|
|
22
|
+
value: number;
|
|
23
|
+
} | null) => void;
|
|
24
|
+
}
|
|
25
|
+
export default class VideoProgressFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<VideoProgressAdapter<P, S>, P, S> {
|
|
26
|
+
constructor(adapter: VideoProgressAdapter<P, S>);
|
|
27
|
+
handleDocumentMouseMove: (e: MouseEvent) => void;
|
|
28
|
+
handleDocumentMouseUp: () => void;
|
|
29
|
+
handleMouseDown: (e: any) => void;
|
|
30
|
+
handleMouseUp: () => void;
|
|
31
|
+
handleMouseEvent: (e: any, shouldSetValue?: boolean) => void;
|
|
32
|
+
handleSliderMouseEnter: (index: number) => void;
|
|
33
|
+
handleSliderMouseLeave: (index: number) => void;
|
|
34
|
+
setActiveIndex: (currentValue: number) => void;
|
|
35
|
+
getValueWidth: (marker: MarkerListItem, value: number) => string;
|
|
36
|
+
getPlayedWidth: (marker: MarkerListItem) => string;
|
|
37
|
+
getLoadedWidth: (marker: MarkerListItem) => string;
|
|
38
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import BaseFoundation from '../base/foundation';
|
|
2
|
+
export default class VideoProgressFoundation extends BaseFoundation {
|
|
3
|
+
constructor(adapter) {
|
|
4
|
+
var _this;
|
|
5
|
+
super(Object.assign({}, adapter));
|
|
6
|
+
_this = this;
|
|
7
|
+
this.handleDocumentMouseMove = e => {
|
|
8
|
+
const {
|
|
9
|
+
isDragging
|
|
10
|
+
} = this.getStates();
|
|
11
|
+
if (isDragging) {
|
|
12
|
+
this.handleMouseEvent(e, true);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
this.handleDocumentMouseUp = () => {
|
|
16
|
+
const {
|
|
17
|
+
isDragging
|
|
18
|
+
} = this.getStates();
|
|
19
|
+
if (isDragging) {
|
|
20
|
+
this._adapter.setIsDragging(false);
|
|
21
|
+
}
|
|
22
|
+
document.removeEventListener('mousemove', this.handleDocumentMouseMove);
|
|
23
|
+
document.removeEventListener('mouseup', this.handleDocumentMouseUp);
|
|
24
|
+
};
|
|
25
|
+
this.handleMouseDown = e => {
|
|
26
|
+
this._adapter.setIsDragging(true);
|
|
27
|
+
this.handleMouseEvent(e, true);
|
|
28
|
+
document.addEventListener('mousemove', this.handleDocumentMouseMove);
|
|
29
|
+
document.addEventListener('mouseup', this.handleDocumentMouseUp);
|
|
30
|
+
};
|
|
31
|
+
this.handleMouseUp = () => {
|
|
32
|
+
const {
|
|
33
|
+
isDragging
|
|
34
|
+
} = this.getStates();
|
|
35
|
+
if (isDragging) {
|
|
36
|
+
this._adapter.setIsDragging(false);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
this.handleMouseEvent = function (e) {
|
|
40
|
+
let shouldSetValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
41
|
+
const {
|
|
42
|
+
isDragging
|
|
43
|
+
} = _this.getStates();
|
|
44
|
+
const {
|
|
45
|
+
onChange,
|
|
46
|
+
max
|
|
47
|
+
} = _this.getProps();
|
|
48
|
+
const sliderRef = _this._adapter.getSliderRef();
|
|
49
|
+
if (!sliderRef) return;
|
|
50
|
+
const rect = sliderRef.getBoundingClientRect();
|
|
51
|
+
const offset = e.clientX - rect.left;
|
|
52
|
+
const total = rect.width;
|
|
53
|
+
const percentage = Math.min(Math.max(offset / total, 0), 1);
|
|
54
|
+
const value = percentage * max;
|
|
55
|
+
if (shouldSetValue && (isDragging || e.type === 'mousedown')) {
|
|
56
|
+
_this.setActiveIndex(value);
|
|
57
|
+
onChange(value);
|
|
58
|
+
}
|
|
59
|
+
_this._adapter.setMovingInfo({
|
|
60
|
+
progress: percentage,
|
|
61
|
+
offset: offset - rect.width / 2,
|
|
62
|
+
value
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
this.handleSliderMouseEnter = index => {
|
|
66
|
+
const {
|
|
67
|
+
value: currentValue
|
|
68
|
+
} = this.getProps();
|
|
69
|
+
const markersList = this._adapter.getMarkersList();
|
|
70
|
+
const currentSlider = markersList[index];
|
|
71
|
+
if (currentSlider.start < currentValue && currentSlider.end > currentValue) {
|
|
72
|
+
this._adapter.setIsHandleHovering(true);
|
|
73
|
+
} else {
|
|
74
|
+
this._adapter.setIsHandleHovering(false);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
this.handleSliderMouseLeave = index => {
|
|
78
|
+
const {
|
|
79
|
+
value: currentValue
|
|
80
|
+
} = this.getProps();
|
|
81
|
+
const markersList = this._adapter.getMarkersList();
|
|
82
|
+
const currentSlider = markersList[index];
|
|
83
|
+
if (currentSlider.start < currentValue && currentSlider.end > currentValue) {
|
|
84
|
+
this._adapter.setIsHandleHovering(false);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
this.setActiveIndex = currentValue => {
|
|
88
|
+
const markersList = this._adapter.getMarkersList();
|
|
89
|
+
markersList.map((marker, index) => {
|
|
90
|
+
if (currentValue < marker.end && currentValue > marker.start) {
|
|
91
|
+
this._adapter.setIsHandleHovering(true);
|
|
92
|
+
this._adapter.setActiveIndex(index);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
this.getValueWidth = (marker, value) => {
|
|
97
|
+
const {
|
|
98
|
+
start,
|
|
99
|
+
end
|
|
100
|
+
} = marker;
|
|
101
|
+
if (value > end) {
|
|
102
|
+
return 'calc(100% - 2px)';
|
|
103
|
+
} else if (value < start) {
|
|
104
|
+
return '0%';
|
|
105
|
+
} else {
|
|
106
|
+
return `${(value - start) / (end - start) * 100}%`;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// Get the width of the video being played
|
|
110
|
+
this.getPlayedWidth = marker => {
|
|
111
|
+
const {
|
|
112
|
+
value: currentValue
|
|
113
|
+
} = this.getProps();
|
|
114
|
+
return this.getValueWidth(marker, currentValue);
|
|
115
|
+
};
|
|
116
|
+
this.getLoadedWidth = marker => {
|
|
117
|
+
const {
|
|
118
|
+
bufferedValue
|
|
119
|
+
} = this.getProps();
|
|
120
|
+
return this.getValueWidth(marker, bufferedValue);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|