@volcengine/veplayer 1.15.1 → 1.15.2-rc.1

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.

Potentially problematic release.


This version of @volcengine/veplayer might be problematic. Click here for more details.

Files changed (245) hide show
  1. package/.changeset/config.json +11 -0
  2. package/.changeset/curvy-yaks-smoke.md +5 -0
  3. package/.changeset/neat-eyes-search.md +5 -0
  4. package/.codebase/pipelines/create-api-doc.yaml +16 -0
  5. package/.eslintignore +5 -0
  6. package/.eslintrc.json +53 -0
  7. package/.stylelintrc.js +51 -0
  8. package/CHANGELOG.md +5665 -0
  9. package/DEV_README.md +39 -0
  10. package/LICENSE +20 -0
  11. package/README_EN.md +46 -0
  12. package/build.sh +44 -0
  13. package/docg.config.js +65 -0
  14. package/env/byteplus.js +30 -0
  15. package/env/volcengine.js +50 -0
  16. package/fixtures/favicon.ico +0 -0
  17. package/fixtures/index.base.js +59 -0
  18. package/fixtures/index.html +41 -0
  19. package/fixtures/index.js +185 -0
  20. package/libd.config.js +147 -0
  21. package/localhost+2-key.pem +28 -0
  22. package/localhost+2.pem +26 -0
  23. package/lux.config.mjs +37 -0
  24. package/package.json +123 -4
  25. package/sdkhub.config.json +10 -0
  26. package/src/@types/global.d.ts +35 -0
  27. package/src/assets/common/error.svg +3 -0
  28. package/src/assets/common/errorImg.png +0 -0
  29. package/src/assets/common/errorImg.svg +12 -0
  30. package/src/assets/icons/mobile/definition.svg +3 -0
  31. package/src/assets/icons/mobile/line.svg +3 -0
  32. package/src/assets/icons/mobile/mobileDanmu.svg +1 -0
  33. package/src/assets/icons/mobile/mobileDanmuAcitive.svg +1 -0
  34. package/src/assets/icons/mobile/mobileDanmuSetting.svg +1 -0
  35. package/src/assets/icons/mobile/mobileExitFullscreen.svg +1 -0
  36. package/src/assets/icons/mobile/mobileFullscreen.svg +1 -0
  37. package/src/assets/icons/mobile/mobilePause.svg +4 -0
  38. package/src/assets/icons/mobile/mobilePlay.svg +4 -0
  39. package/src/assets/icons/mobile/mobilePlaynext.svg +1 -0
  40. package/src/assets/icons/mobile/mobileRefresh.svg +1 -0
  41. package/src/assets/icons/mobile/more.svg +3 -0
  42. package/src/assets/icons/mobile/muted.svg +22 -0
  43. package/src/assets/icons/mobile/playbackrate.svg +3 -0
  44. package/src/assets/icons/pc/danmu.svg +1 -0
  45. package/src/assets/icons/pc/danmuActive.svg +1 -0
  46. package/src/assets/icons/pc/danmuSettings.svg +1 -0
  47. package/src/assets/icons/pc/download.svg +14 -0
  48. package/src/assets/icons/pc/exitFullscreen.svg +1 -0
  49. package/src/assets/icons/pc/exitMirror.svg +10 -0
  50. package/src/assets/icons/pc/extend.svg +1 -0
  51. package/src/assets/icons/pc/fullscreen.svg +1 -0
  52. package/src/assets/icons/pc/getMirror.svg +10 -0
  53. package/src/assets/icons/pc/list.svg +20 -0
  54. package/src/assets/icons/pc/noPoster.svg +119 -0
  55. package/src/assets/icons/pc/pause.svg +1 -0
  56. package/src/assets/icons/pc/pip.svg +1 -0
  57. package/src/assets/icons/pc/pipExit.svg +1 -0
  58. package/src/assets/icons/pc/play-next-btn.svg +4 -0
  59. package/src/assets/icons/pc/play.svg +1 -0
  60. package/src/assets/icons/pc/playNext.svg +1 -0
  61. package/src/assets/icons/pc/playerLoading.svg +1 -0
  62. package/src/assets/icons/pc/refresh.svg +1 -0
  63. package/src/assets/icons/pc/replay.svg +1 -0
  64. package/src/assets/icons/pc/reset.svg +6 -0
  65. package/src/assets/icons/pc/startPlay.svg +1 -0
  66. package/src/assets/icons/pc/subtitleclose.svg +5 -0
  67. package/src/assets/icons/pc/subtitleopen.svg +3 -0
  68. package/src/assets/icons/pc/theaterEnter.svg +1 -0
  69. package/src/assets/icons/pc/theaterExit.svg +1 -0
  70. package/src/assets/icons/pc/volumeLarge.svg +1 -0
  71. package/src/assets/icons/pc/volumeMuted.svg +1 -0
  72. package/src/assets/icons/pc/volumeSmall.svg +1 -0
  73. package/src/config/defaultPreset.ts +110 -0
  74. package/src/config/playerOptionMobile.ts +166 -0
  75. package/src/config/playerOptionPc.ts +147 -0
  76. package/src/config/playerPreset.ts +242 -0
  77. package/src/constants/api.ts +13 -0
  78. package/src/constants/event.ts +577 -0
  79. package/src/constants/player.ts +84 -0
  80. package/src/constants/plugin.ts +19 -0
  81. package/src/constants/umdMap.ts +137 -0
  82. package/src/constants/umdPlugins.json +68 -0
  83. package/src/core/index.ts +7 -0
  84. package/src/core/player.ts +2713 -0
  85. package/src/core/playerData.ts +812 -0
  86. package/src/env.d.ts +47 -0
  87. package/src/index.ts +24 -0
  88. package/src/index.umd.ts +54 -0
  89. package/src/interface/adaptRange.d.ts +33 -0
  90. package/src/interface/api.ts +132 -0
  91. package/src/interface/autoBitrate.d.ts +41 -0
  92. package/src/interface/index.ts +1685 -0
  93. package/src/interface/rtm.ts +56 -0
  94. package/src/interface/sdkErrorPlugin.ts +145 -0
  95. package/src/interface/subtitle.ts +381 -0
  96. package/src/interface/video.ts +107 -0
  97. package/src/interface/xgplayer.ts +748 -0
  98. package/src/lang/constants.ts +69 -0
  99. package/src/lang/en.ts +98 -0
  100. package/src/lang/index.ts +33 -0
  101. package/src/lang/jp.ts +100 -0
  102. package/src/lang/zh-hk.ts +80 -0
  103. package/src/lang/zh.ts +79 -0
  104. package/src/license/index.ts +315 -0
  105. package/src/license/ttlicense2.js +15 -0
  106. package/src/license/ttlicense2.wasm +0 -0
  107. package/src/music/icons/back.svg +3 -0
  108. package/src/music/icons/forward.svg +3 -0
  109. package/src/music/icons/loop.svg +10 -0
  110. package/src/music/icons/order.svg +10 -0
  111. package/src/music/icons/pause-circle.svg +23 -0
  112. package/src/music/icons/play-circle.svg +22 -0
  113. package/src/music/icons/random.svg +10 -0
  114. package/src/music/icons/sloop.svg +10 -0
  115. package/src/music/index.ts +5 -0
  116. package/src/music/music.ts +550 -0
  117. package/src/music/plugins/index.less +185 -0
  118. package/src/music/plugins/index.ts +6 -0
  119. package/src/music/plugins/musicBackward.ts +82 -0
  120. package/src/music/plugins/musicCover.ts +45 -0
  121. package/src/music/plugins/musicForward.ts +82 -0
  122. package/src/music/plugins/musicMeta.ts +32 -0
  123. package/src/music/plugins/musicMode.ts +152 -0
  124. package/src/music/plugins/musicNext.ts +93 -0
  125. package/src/music/plugins/musicPrev.ts +94 -0
  126. package/src/music/preset.ts +69 -0
  127. package/src/music/xhr.ts +37 -0
  128. package/src/plugins/common/extendPluginFactory.ts +132 -0
  129. package/src/plugins/common/mobilePlayerPanel.ts +253 -0
  130. package/src/plugins/external/LiveInfoPanel.ts +340 -0
  131. package/src/plugins/external/ad/adsPlugin.ts +1 -0
  132. package/src/plugins/external/aiSubtitleIconPlugin.ts +270 -0
  133. package/src/plugins/external/aiSubtitlePlugin.ts +452 -0
  134. package/src/plugins/external/definitionDemotePlugin.ts +591 -0
  135. package/src/plugins/external/memoryPlay.ts +247 -0
  136. package/src/plugins/external/mirrorPlugin.ts +141 -0
  137. package/src/plugins/external/playList/OptionList.ts +204 -0
  138. package/src/plugins/external/playList/index.ts +743 -0
  139. package/src/plugins/external/subtitle/index.ts +672 -0
  140. package/src/plugins/external/subtitle/nativeSubTitle.ts +115 -0
  141. package/src/plugins/external/timeShiftPlugin.ts +484 -0
  142. package/src/plugins/external/watermark/dynamicWatermark.less +13 -0
  143. package/src/plugins/external/watermark/dynamicWatermark.ts +449 -0
  144. package/src/plugins/external/watermark/dynamicWatermarkPlugin.ts +185 -0
  145. package/src/plugins/inner/common/autoplayPlugin.ts +435 -0
  146. package/src/plugins/inner/common/danmu/container.ts +120 -0
  147. package/src/plugins/inner/common/danmu/index.ts +683 -0
  148. package/src/plugins/inner/common/danmu/lang.ts +139 -0
  149. package/src/plugins/inner/common/danmu/panel.ts +20 -0
  150. package/src/plugins/inner/common/danmu/slider.ts +210 -0
  151. package/src/plugins/inner/common/danmu/state.ts +118 -0
  152. package/src/plugins/inner/common/danmu/switch.ts +74 -0
  153. package/src/plugins/inner/common/definitionBasePlugin.ts +353 -0
  154. package/src/plugins/inner/common/errorPlugin.ts +544 -0
  155. package/src/plugins/inner/common/liveLogger.ts +137 -0
  156. package/src/plugins/inner/common/poster/index.less +66 -0
  157. package/src/plugins/inner/common/poster/index.ts +178 -0
  158. package/src/plugins/inner/common/refreshPlugin.ts +88 -0
  159. package/src/plugins/inner/common/rtmPlugin.ts +62 -0
  160. package/src/plugins/inner/common/toastPlugin.ts +90 -0
  161. package/src/plugins/inner/common/unmutePlugin.ts +133 -0
  162. package/src/plugins/inner/common/vodLogger.ts +80 -0
  163. package/src/plugins/inner/mobile/DefinitionMobilePlugin.ts +217 -0
  164. package/src/plugins/inner/mobile/LineMobilePlugins.ts +169 -0
  165. package/src/plugins/inner/mobile/MoreButtonPlugin.ts +176 -0
  166. package/src/plugins/inner/mobile/PlaybackRatePlugin.ts +199 -0
  167. package/src/plugins/inner/pc/definitionPlugin.ts +203 -0
  168. package/src/plugins/inner/pc/multilinePlugin.ts +93 -0
  169. package/src/sdkPlugin/abr.ts +67 -0
  170. package/src/sdkPlugin/adaptRange.ts +49 -0
  171. package/src/sdkPlugin/authToken.ts +557 -0
  172. package/src/sdkPlugin/sdkPlugin.ts +125 -0
  173. package/src/sdkPlugin/sdkPluginManager.ts +157 -0
  174. package/src/sdkPlugin/strategy.ts +47 -0
  175. package/src/strategy/index.ts +740 -0
  176. package/src/strategy/vestrategy-h265-wrapper.ts +34 -0
  177. package/src/strategy/vestrategy-preload-wrapper.ts +414 -0
  178. package/src/streamAdapters/base.ts +89 -0
  179. package/src/streamAdapters/dash.ts +230 -0
  180. package/src/streamAdapters/default.ts +53 -0
  181. package/src/streamAdapters/hls.ts +278 -0
  182. package/src/streamAdapters/index.ts +40 -0
  183. package/src/streamAdapters/mp4.ts +214 -0
  184. package/src/style/bytelive/danmu.less +293 -0
  185. package/src/style/bytelive/definitionIcon.less +80 -0
  186. package/src/style/bytelive/error.less +165 -0
  187. package/src/style/bytelive/index.less +62 -0
  188. package/src/style/bytelive/loading.less +5 -0
  189. package/src/style/bytelive/mobiePlugin.less +2 -0
  190. package/src/style/bytelive/mobile.less +76 -0
  191. package/src/style/bytelive/moreButton.less +79 -0
  192. package/src/style/bytelive/panel.less +259 -0
  193. package/src/style/bytelive/pc.less +161 -0
  194. package/src/style/bytelive/refresh.less +3 -0
  195. package/src/style/bytelive/reset.less +4 -0
  196. package/src/style/bytelive/toast.less +61 -0
  197. package/src/style/bytelive/unmute.less +65 -0
  198. package/src/style/external/LiveInfoPanel.less +41 -0
  199. package/src/style/external/aisub.less +139 -0
  200. package/src/style/external/aisubIcon.less +25 -0
  201. package/src/style/external/index.less +5 -0
  202. package/src/style/external/larkWindow.less +36 -0
  203. package/src/style/external/mirror.less +27 -0
  204. package/src/style/external/playList.less +258 -0
  205. package/src/style/external/timeShift.less +102 -0
  206. package/src/style/external/vttSubtitle.less +25 -0
  207. package/src/utils/debug.ts +62 -0
  208. package/src/utils/definition.ts +61 -0
  209. package/src/utils/escapeHtml.ts +93 -0
  210. package/src/utils/eventMiddleWare.ts +108 -0
  211. package/src/utils/index.ts +621 -0
  212. package/src/utils/intervalTimer.ts +38 -0
  213. package/src/utils/isHijackBrowser.ts +71 -0
  214. package/src/utils/proxy.ts +139 -0
  215. package/src/utils/storage.ts +34 -0
  216. package/src/utils/time.ts +19 -0
  217. package/src/utils/toast/index.less +20 -0
  218. package/src/utils/toast/index.ts +21 -0
  219. package/src/utils/token.ts +395 -0
  220. package/src/utils/u8a.ts +4 -0
  221. package/src/utils/umdLoader.ts +193 -0
  222. package/src/utils/video.ts +43 -0
  223. package/src/utils/xhr.ts +160 -0
  224. package/src/veError/error.ts +301 -0
  225. package/src/veError/index.ts +681 -0
  226. package/src/veError/playerProxy.ts +69 -0
  227. package/tsconfig.json +27 -0
  228. package/index.d.ts +0 -6874
  229. package/index.min.css +0 -1
  230. package/index.min.js +0 -2
  231. package/plugin/DashAbralgo.js +0 -2
  232. package/plugin/XGVideo.js +0 -2
  233. package/plugin/danmuMask.js +0 -2
  234. package/plugin/danmujs.js +0 -3
  235. package/plugin/dash.js +0 -2
  236. package/plugin/flv.js +0 -2
  237. package/plugin/hls.js +0 -2
  238. package/plugin/hlsEncrypt.js +0 -2
  239. package/plugin/mp4Encrypt.js +0 -2
  240. package/plugin/preloader.js +0 -2
  241. package/plugin/streamprobe.js +0 -2
  242. package/plugin/vestrategy.js +0 -1
  243. package/plugin/vestrategy_adapt_range.js +0 -1
  244. package/plugin/vestrategy_h265.js +0 -1
  245. package/plugin/vestrategy_preload.js +0 -1
@@ -0,0 +1,683 @@
1
+ import { Plugin, Sniffer, Events } from 'xgplayer';
2
+ import openIcon from '../../../../assets/icons/pc/danmuActive.svg';
3
+ import closeIcon from '../../../../assets/icons/pc/danmu.svg';
4
+ import resetIcon from '../../../../assets/icons/pc/reset.svg';
5
+ import helpers from 'dom-helpers';
6
+ import Slider from './slider';
7
+ import State from './state';
8
+ import Container from './container';
9
+ import Panel from './panel';
10
+ import Switch from './switch';
11
+ import type { SwitchInstance } from './switch';
12
+ import EventEmitter from 'eventemitter3';
13
+ import debounce from 'lodash-es/debounce';
14
+ import { PluginEvents } from '@/constants/event';
15
+ import { CONTROL_ICON_INDEX } from '@/constants/plugin';
16
+
17
+ declare global {
18
+ interface Window {
19
+ DanmuMask?: any;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * @brief 弹幕配置。
25
+ * @list Options
26
+ * @kind property
27
+ */
28
+ /** {en}
29
+ * @list Options
30
+ * @kind property
31
+ */
32
+ export interface IDanmuConfig {
33
+ /**
34
+ * @brief 弹幕透明度。取值如下:
35
+ *
36
+ * - `0`:透明度 0。
37
+ * - `33`:透明度 33%。
38
+ * - `66`:透明度 66%。
39
+ * - `99`:透明度 100%。
40
+ * @default 99
41
+ */
42
+ /** {en}
43
+ * @brief 透明度, 枚举值[0, 33, 66, 99], 实际对应0, 0.33, 0.66, 1
44
+ */
45
+ opacity?: number;
46
+ /**
47
+ * @brief 弹幕区域大小。取值如下:
48
+ *
49
+ * - `0`:弹幕区域占全屏的 1/4。
50
+ * - `33`:弹幕区域占全屏的 1/2。
51
+ * - `66`:弹幕区域占全屏的 3/4。
52
+ * - `99`:弹幕区域占满全屏。
53
+ * @default 99
54
+ */
55
+ /** {en}
56
+ * @brief 枚举值[0, 33, 66, 99] 实际对应1/4, 1/2, 3/4, 1
57
+ */
58
+ area?: number;
59
+ /**
60
+ * @brief 弹幕滚动速度。取值如下:
61
+ *
62
+ * - `0`:弹幕速度为 1/4。
63
+ * - `20`:弹幕速度为 1/2。
64
+ * - `40`:弹幕速度为 1。
65
+ * - `60`:弹幕速度为 5/4。
66
+ * - `80`:弹幕速度为 3/2。
67
+ * - `100`:弹幕速度为 2。
68
+ * @default 40
69
+ */
70
+ /** {en}
71
+ * @brief 速度, 枚举值[0, 20, 40, 60, 80, 100], 实际对应1/4, 1/2,1,5/4,3/2,2
72
+ */
73
+ speed?: number;
74
+ /**
75
+ * @brief 弹幕字体大小。取值如下:
76
+ *
77
+ * - `0`:字体大小为 14 px。
78
+ * - `50`:字体大小为 16 px。
79
+ * - `100`:字体大小为 20 px。
80
+ * @default 50
81
+ */
82
+ /** {en}
83
+ * @brief 字体大小, 枚举值[0, 50, 100],实际对应14px 16px 20px
84
+ */
85
+ fontSize?: number;
86
+ /**
87
+ * @brief 是否默认开启弹幕。取值如下:
88
+ *
89
+ * - `false`:关闭。
90
+ * - `true`:开启。
91
+ * @default false
92
+ */
93
+ /** {en}
94
+ * @brief 是否默认开启弹幕
95
+ */
96
+ active?: boolean;
97
+ /**
98
+ * @brief 是否展示弹幕设置面板。取值如下:
99
+ *
100
+ * - `false`:不展示弹幕设置面板。
101
+ * - `true`:展示弹幕设置面板。
102
+ * @default true
103
+ * @hidden
104
+ */
105
+ /** {en}
106
+ * @brief Whether to enable barrage by default
107
+ */
108
+ usePanel?: boolean;
109
+ /**
110
+ * @brief 弹幕列表。
111
+ * @default -
112
+ */
113
+ /** {en}
114
+ * @brief 弹幕列表
115
+ */
116
+ danmuItems?: DanmuItem[];
117
+ /**
118
+ * @hidden
119
+ * @type {ExternalItem[]}
120
+ * @memberof IDanmuConfig
121
+ */
122
+ external?: ExternalItem[];
123
+ /**
124
+ * @brief 蒙版弹幕配置
125
+ * @default -
126
+ */
127
+ maskConfig?: IMaskConfig;
128
+ /**
129
+ * @brief 是否开启蒙版弹幕,即对应智能挡板开关
130
+ * @default false
131
+ */
132
+ maskActive?: boolean;
133
+ }
134
+
135
+ interface IMaskConfig {
136
+ maskUrl: string;
137
+ maskOffset?: number;
138
+ interval?: number;
139
+ }
140
+
141
+ /** {zh}
142
+ * @hidden
143
+ * @brief 语言类型
144
+ */
145
+ /** {en}
146
+ * @hidden
147
+ * @brief 语言类型
148
+ */
149
+ interface Lang {
150
+ zh: string;
151
+ en: string;
152
+ [props: string]: string;
153
+ }
154
+ /** {zh}
155
+ * @brief 弹幕项
156
+ * @list Options
157
+ * @kind property
158
+ * @export
159
+ * @interface DanmuItem
160
+ */
161
+ /** {en}
162
+ * @list Options
163
+ * @kind property
164
+ * @export
165
+ * @interface DanmuItem
166
+ * @brief 弹幕项
167
+ */
168
+ export interface DanmuItem {
169
+ /**
170
+ * 弹幕唯一id
171
+ *
172
+ * @type {string}
173
+ * @memberof DanmuItem
174
+ * @brief 弹幕唯一 ID。
175
+ */
176
+ /** {en}
177
+ * @brief 弹幕唯一id
178
+ */
179
+ id: string;
180
+ /**
181
+ * 弹幕文案
182
+ *
183
+ * @type {string}
184
+ * @memberof DanmuItem
185
+ * @brief 弹幕文案。
186
+ */
187
+ /** {en}
188
+ * @brief 弹幕文案
189
+ */
190
+ txt: string;
191
+ /**
192
+ * 弹幕出现时间, 单位为ms
193
+ * @default 0
194
+ * @brief 弹幕出现时间,单位为毫秒。
195
+ */
196
+ /** {en}
197
+ * @brief 弹幕出现时间, 单位为ms
198
+ */
199
+ start?: number; // 弹幕出现时间 ms
200
+ /**
201
+ * 是否优先显示
202
+ * @hidden
203
+ * @type {boolean}
204
+ * @memberof DanmuItem
205
+ */
206
+ prior?: boolean; // 优先显示
207
+ /**
208
+ * 弹幕持续显示时间, 单位为ms
209
+ * @default 5000
210
+ *
211
+ * @type {number}
212
+ * @memberof DanmuItem
213
+ * @brief 弹幕持续显示时长,单位为毫秒。
214
+ */
215
+ /** {en}
216
+ * @brief 弹幕持续显示时间, 单位为ms
217
+ */
218
+ duration?: number;
219
+ /**
220
+ * @brief 弹幕样式。示例如下:`style : { color: '#ff9500', fontSize: '20px', padding: '2px 11px'}`
221
+ * @example
222
+ * ``` javascript
223
+ * {
224
+ * color: '#ff9500',
225
+ * fontSize: '20px',
226
+ * padding: '2px 11px'
227
+ * }
228
+ *```
229
+ * @type {Partial<Record<Property, string>>}
230
+ * @memberof DanmuItem
231
+ */
232
+ /** {en}
233
+ * @brief 弹幕样式
234
+ */
235
+ style?: CSSStyleDeclaration;
236
+ }
237
+ // 主题样式
238
+ export interface ExternalItem {
239
+ key: string;
240
+ name: string;
241
+ value: boolean;
242
+ lang?: Lang;
243
+ }
244
+
245
+ // 数值配置
246
+ export interface SliderItemProps {
247
+ key: string;
248
+ name: string;
249
+ defaultValue: number;
250
+ ticks: Tick[];
251
+ }
252
+ //
253
+ export interface Tick {
254
+ name: string;
255
+ val: number;
256
+ renderVal: number;
257
+ }
258
+
259
+ const isPC = Sniffer.device === 'pc';
260
+ const MIN_INTERVAL = 300;
261
+ const { POSITIONS } = Plugin;
262
+
263
+ export default class DanmuPlugin extends Plugin {
264
+ // 播放器值
265
+
266
+ public iconWrap: HTMLElement;
267
+ public tipsWrap: HTMLElement;
268
+ public panel: Panel;
269
+ public container: Container;
270
+ public state: State;
271
+ public mask: any;
272
+ public seekCost = window.performance.now();
273
+
274
+ public eventBus = new EventEmitter();
275
+
276
+ /** 移动端 - 设置panel里的弹幕开关 */
277
+ public danmuSwitchInSettingPanel: SwitchInstance;
278
+ static get pluginName() {
279
+ return 'DanmuPlugin';
280
+ }
281
+
282
+ static get defaultConfig() {
283
+ return {
284
+ position: POSITIONS.CONTROLS_RIGHT,
285
+ index: CONTROL_ICON_INDEX.DanmuPlugin,
286
+ };
287
+ }
288
+ constructor(args: any) {
289
+ super(args);
290
+ // 依赖全局的danmu.js
291
+ if (!window['danmu.js']) return;
292
+
293
+ this.state = new State(args.config);
294
+ this.state.updateLang(this.player.lang);
295
+ this.iconWrap = document.createElement('div');
296
+ helpers.addClass(this.iconWrap, 'icon-warp');
297
+ this.tipsWrap = document.createElement('div');
298
+ helpers.addClass(this.tipsWrap, 'tips-wrap');
299
+
300
+ this.container = new Container(this.state, this.player);
301
+ this.panel = new Panel(this.state);
302
+ }
303
+
304
+ afterCreate() {
305
+ this.player.root?.appendChild(this.container.root);
306
+ this.renderIcon();
307
+ this.renderBox();
308
+ this.root.appendChild(this.iconWrap);
309
+
310
+ // pc端需要render tips 且 panel要挂载到danmu dom 下
311
+ if (isPC) {
312
+ // 使用设置面板
313
+ if (this.state.getConfig().usePanel) {
314
+ this.root.appendChild(this.panel.root);
315
+ }
316
+ this.renderTips();
317
+ helpers.addClass(this.panel.root, 'pc-panel');
318
+ this.root.appendChild(this.tipsWrap);
319
+ }
320
+
321
+ this.initEvents();
322
+ this.container.initDanmuContainer();
323
+ }
324
+
325
+ afterPlayerInit() {
326
+ // 初始化弹幕蒙版
327
+ this.initDanmuMask();
328
+ }
329
+
330
+ updateLang(lang: string): void {
331
+ this.state.updateLang(this.player.lang);
332
+ this.eventBus.emit('updateLang');
333
+ }
334
+
335
+ registerIcons() {
336
+ return {
337
+ open: {
338
+ icon: openIcon,
339
+ class: 'xgplayer-danmu-open-svg',
340
+ },
341
+ close: {
342
+ icon: closeIcon,
343
+ class: 'xgplayer-danmu-close-svg',
344
+ },
345
+ reset: {
346
+ icon: resetIcon,
347
+ class: 'xgplayer-danmu-reset-svg',
348
+ },
349
+ };
350
+ }
351
+
352
+ initEvents() {
353
+ if (isPC) {
354
+ this.bindPCEvent();
355
+ } else {
356
+ //
357
+ this.bindMobileEvent();
358
+ }
359
+ this.bindPlayerEvent();
360
+ }
361
+
362
+ start() {
363
+ if (!this.container) {
364
+ return;
365
+ }
366
+ this.container.start();
367
+ if (this.player.paused) {
368
+ this.container.pause();
369
+ }
370
+ }
371
+
372
+ bindPlayerEvent() {
373
+ const active = this.state.getConfig()?.active;
374
+ this.once(Events.TIME_UPDATE, () => {
375
+ active && this.start();
376
+ });
377
+ this.on(Events.PAUSE, () => {
378
+ this.container.pause();
379
+ });
380
+ this.on(Events.PLAY, () => {
381
+ this.container.play();
382
+ });
383
+ this.on(Events.SEEKING, () => {
384
+ this.seekCost = window.performance.now();
385
+ this.container.stop();
386
+ });
387
+ this.on(
388
+ Events.SEEKED,
389
+ debounce(() => {
390
+ this.container.start();
391
+ }, MIN_INTERVAL),
392
+ );
393
+ this.on(
394
+ [
395
+ Events.FULLSCREEN_CHANGE,
396
+ Events.CSS_FULLSCREEN_CHANGE,
397
+ Events.MINI_STATE_CHANGE,
398
+ ],
399
+ () => {
400
+ this.container.resize();
401
+ this.handleResize();
402
+ },
403
+ );
404
+
405
+ this.on(Events.PIP_CHANGE, this.handlePIP.bind(this));
406
+ }
407
+
408
+ bindPCEvent() {
409
+ helpers.addEventListener(this.root, 'click', this.onClick.bind(this));
410
+ helpers.addEventListener(this.root, 'mouseenter', () => {
411
+ const active = this.state.getConfig().active;
412
+ const { controls } = this.player;
413
+ const { listType } = this.config;
414
+ listType === 'rightSide' ? controls.blur() : controls.focus();
415
+ if (active) {
416
+ helpers.style(this.panel.root, { display: 'block' });
417
+ helpers.style(this.tipsWrap, { display: 'none' });
418
+ } else {
419
+ helpers.style(this.panel.root, { display: 'none' });
420
+ helpers.style(this.tipsWrap, { display: 'block' });
421
+ }
422
+ });
423
+ helpers.addEventListener(this.root, 'mouseleave', () => {
424
+ const { controls } = this.player;
425
+ const { listType } = this.config;
426
+ listType === 'rightSide' ? controls.focus() : controls.focusAwhile();
427
+ helpers.style(this.panel.root, { display: 'none' });
428
+ helpers.style(this.tipsWrap, { display: 'none' });
429
+ });
430
+ }
431
+
432
+ bindMobileEvent() {
433
+ helpers.addEventListener(this.root, 'click', () => {
434
+ if (this.state.getConfig().usePanel) {
435
+ (this.player as any).panel.showPanel(this.panel.root);
436
+ } else {
437
+ this.onClick();
438
+ }
439
+ });
440
+ }
441
+
442
+ onClick() {
443
+ this.toggleDanmu();
444
+ this.renderIcon();
445
+ }
446
+
447
+ toggleDanmu() {
448
+ const { active, maskActive } = this.state.getConfig();
449
+ const willChange = !active;
450
+
451
+ if (willChange) {
452
+ this.state.updateConfig({ active: willChange });
453
+ if (maskActive) {
454
+ this.initMask();
455
+ }
456
+ this?.container.start();
457
+ } else {
458
+ this?.container.stop();
459
+ this.destroyMask();
460
+ this.state.updateConfig({ active: willChange });
461
+ }
462
+
463
+ this.player.emit(PluginEvents.DANMU_CHANGE, { active: willChange });
464
+
465
+ if (this.danmuSwitchInSettingPanel) {
466
+ this.danmuSwitchInSettingPanel.value = willChange;
467
+ this.danmuSwitchInSettingPanel.render();
468
+ }
469
+ }
470
+
471
+ renderIcon() {
472
+ this.iconWrap.innerHTML = '';
473
+ if (this.state.getConfig().active) {
474
+ this.iconWrap.appendChild((this.icons as any).open);
475
+ } else {
476
+ this.iconWrap.appendChild((this.icons as any).close);
477
+ }
478
+ }
479
+
480
+ renderTips() {
481
+ this.tipsWrap.innerHTML = this.state.curLangMap.openDanmu;
482
+ }
483
+
484
+ renderBox() {
485
+ this.panel.root.innerHTML = '';
486
+ const header = document.createElement('div');
487
+ helpers.addClass(header, 'box-header');
488
+ header.innerHTML =
489
+ '<div class="header-setting">' +
490
+ this.state.curLangMap.danmuSetting +
491
+ '</div> <div class="header-reset"></div>';
492
+ const reset = header.querySelector('.header-reset') as HTMLElement;
493
+ reset.appendChild((this.icons as any).reset);
494
+ helpers.addEventListener(
495
+ reset,
496
+ 'click',
497
+ event => {
498
+ event.stopPropagation();
499
+ this.eventBus.emit('reset');
500
+ },
501
+ {
502
+ capture: true,
503
+ },
504
+ );
505
+ const span = document.createElement('span');
506
+ span.innerHTML = this.state.curLangMap.reset;
507
+ reset.appendChild(span);
508
+ this.eventBus.on('updateLang', () => {
509
+ span.innerHTML = this.state.curLangMap.reset;
510
+ header.querySelector('.header-setting').innerHTML =
511
+ this.state.curLangMap.danmuSetting;
512
+ });
513
+ this.panel.root.appendChild(header);
514
+ if (!isPC) {
515
+ // render turnOff
516
+ this.renderTurnOff();
517
+ }
518
+ this.renderSliders();
519
+ this.renderSwitches();
520
+ }
521
+
522
+ renderTurnOff() {
523
+ const item = {
524
+ name: this.state.curLangMap.danmuSwitch,
525
+ key: 'active',
526
+ value: this.state.getConfig().active || false,
527
+ };
528
+ const turnOff = new Switch(item);
529
+ this.danmuSwitchInSettingPanel = turnOff;
530
+ this.panel.root.appendChild(turnOff.root);
531
+ turnOff.onChange((val: boolean) => {
532
+ this.toggleDanmu();
533
+ this.renderIcon();
534
+ });
535
+ this.eventBus.on('updateLang', () => {
536
+ turnOff.renderName(this.state.curLangMap.danmuSwitch);
537
+ });
538
+ }
539
+
540
+ renderSwitches() {
541
+ this.state.getConfig().external?.forEach(item => {
542
+ const switchInstance = new Switch(item);
543
+ this.panel.root.appendChild(switchInstance.root);
544
+ this.eventBus.on('updateLang', () => {
545
+ switchInstance.renderName(item.name);
546
+ });
547
+ switchInstance.onChange((val: boolean) => {
548
+ const external = this.state.getConfig().external || [];
549
+ external.forEach(el => {
550
+ if (el.key === item.key) {
551
+ el.value = val;
552
+ }
553
+ });
554
+ this.state.updateConfig({ external });
555
+ this.player.emit(PluginEvents.DANMU_CHANGE, { external });
556
+ });
557
+ });
558
+ }
559
+
560
+ renderSliders() {
561
+ this.state.sliderItemsProps.forEach((el, index) => {
562
+ const line = document.createElement('div');
563
+
564
+ const slider = new Slider(line, el);
565
+ if (this.state.getConfig()?.[el.key] != undefined) {
566
+ slider.setValue(this.state.getConfig()?.[el.key]);
567
+ }
568
+
569
+ // slider value change
570
+ slider.onChange((val: number) => {
571
+ this.state.updateConfig({ [el.key]: val });
572
+ this.player.emit(PluginEvents.DANMU_CHANGE, { [el.key]: val });
573
+ this.container.setProperty(el.key as any, val);
574
+ });
575
+
576
+ this.eventBus.on('reset', () => {
577
+ slider.setValue(el.defaultValue);
578
+ });
579
+ this.eventBus.on('updateLang', () => {
580
+ slider.renderText(this.state.sliderItemsProps[index]);
581
+ });
582
+ this.panel.root.appendChild(line);
583
+ });
584
+ }
585
+
586
+ sendDanmu(item) {
587
+ return this.container.sendDanmu(item);
588
+ }
589
+
590
+ updateConfig(config = {}) {
591
+ return this.state.updateConfig(config);
592
+ }
593
+
594
+ getConfig() {
595
+ return this.state.getConfig();
596
+ }
597
+
598
+ initDanmuMask() {
599
+ if (!this.player) return;
600
+ const { maskConfig, active, maskActive } = this.state.getConfig();
601
+ if (!maskConfig.maskUrl) return;
602
+
603
+ // 渲染按钮
604
+ this.renderDanmuMaskTurnOff();
605
+
606
+ if (active && maskActive) {
607
+ this.initMask();
608
+ }
609
+ }
610
+
611
+ renderDanmuMaskTurnOff() {
612
+ const item = {
613
+ name: this.state.curLangMap.danmuMask,
614
+ key: 'maskActive',
615
+ value: this.state.getConfig().maskActive || false,
616
+ };
617
+ const turnOff = new Switch(item);
618
+ this.panel.root.appendChild(turnOff.root);
619
+ turnOff.onChange((val: boolean) => {
620
+ this.state.updateConfig({ maskActive: val });
621
+ if (val) {
622
+ this.initMask();
623
+ } else {
624
+ this.destroyMask();
625
+ }
626
+ this.renderIcon();
627
+ });
628
+ this.eventBus.on('updateLang', () => {
629
+ turnOff.renderName(this.state.curLangMap.danmuMask);
630
+ });
631
+ }
632
+
633
+ initMask() {
634
+ this.destroyMask();
635
+ const { maskConfig, maskActive, active } = this.state.getConfig();
636
+ if (!maskConfig.maskUrl) return;
637
+ if (!maskActive) return;
638
+ if (!active) return;
639
+ if (window.DanmuMask && typeof window.DanmuMask === 'function') {
640
+ this.mask = new window.DanmuMask({
641
+ player: this.player,
642
+ url: maskConfig.maskUrl,
643
+ originStart: maskConfig.maskOffset,
644
+ interval: maskConfig.interval,
645
+ });
646
+ }
647
+ this.mask.init();
648
+ }
649
+
650
+ destroyMask() {
651
+ if (this.mask) {
652
+ this.mask.destroy();
653
+ this.mask = null;
654
+ }
655
+ }
656
+
657
+ handleResize() {
658
+ if (!this.mask) return;
659
+ const player = this.player;
660
+ this.mask.setContainerSize(
661
+ player?.root?.offsetWidth ?? 0,
662
+ player?.root?.offsetHeight ?? 0,
663
+ );
664
+ }
665
+
666
+ handlePIP(state) {
667
+ if (state) {
668
+ this.destroyMask();
669
+ } else {
670
+ this.initMask();
671
+ }
672
+ }
673
+
674
+ destroy() {
675
+ this.destroyMask();
676
+ this.container.destroy();
677
+ this.panel.destroy();
678
+ }
679
+
680
+ render() {
681
+ return '<div class="xgplayer-danmu"></div>';
682
+ }
683
+ }