eplayer 1.6.5 → 1.6.8
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/docs/eplayer.js +212 -58
- package/docs/index.html +6 -1
- package/package.json +1 -1
package/docs/eplayer.js
CHANGED
|
@@ -4,8 +4,17 @@ class Eplayer extends HTMLElement {
|
|
|
4
4
|
this.doms = {}
|
|
5
5
|
this.src = this.getAttribute('src')
|
|
6
6
|
this.type = this.getAttribute('type')
|
|
7
|
+
this.cover = this.getAttribute('cover')
|
|
7
8
|
this.live = JSON.parse(this.getAttribute('live'))
|
|
8
9
|
this.danmaku = null
|
|
10
|
+
this.subs = []
|
|
11
|
+
|
|
12
|
+
// 添加长按右箭头3倍速相关状态
|
|
13
|
+
this.rightKeyHoldTimer = null
|
|
14
|
+
this.rightKeyPressTime = null
|
|
15
|
+
this.originalPlaybackRate = 1
|
|
16
|
+
this.isRightKeyPressed = false
|
|
17
|
+
this.isSpeedModeActive = false
|
|
9
18
|
|
|
10
19
|
this.init()
|
|
11
20
|
this.stream()
|
|
@@ -36,11 +45,14 @@ class Eplayer extends HTMLElement {
|
|
|
36
45
|
this.$('.time').style.display = 'inline-block'
|
|
37
46
|
}
|
|
38
47
|
}
|
|
39
|
-
if (name === '
|
|
48
|
+
if (name === 'danmu') {
|
|
40
49
|
this.danmaku.add({
|
|
41
50
|
msg: newVal
|
|
42
51
|
})
|
|
43
52
|
}
|
|
53
|
+
if (name === 'cover') {
|
|
54
|
+
this.cover = newVal
|
|
55
|
+
}
|
|
44
56
|
}
|
|
45
57
|
|
|
46
58
|
$(key) {
|
|
@@ -82,10 +94,12 @@ class Eplayer extends HTMLElement {
|
|
|
82
94
|
this.video.play()
|
|
83
95
|
this.danmaku.resume()
|
|
84
96
|
this.$('.is-play').setAttribute('icon-id', 'pause')
|
|
97
|
+
this.emit('play')
|
|
85
98
|
} else {
|
|
86
99
|
this.video.pause()
|
|
87
100
|
this.danmaku.pause()
|
|
88
101
|
this.$('.is-play').setAttribute('icon-id', 'play')
|
|
102
|
+
this.emit('pause')
|
|
89
103
|
}
|
|
90
104
|
}
|
|
91
105
|
|
|
@@ -112,64 +126,143 @@ class Eplayer extends HTMLElement {
|
|
|
112
126
|
}
|
|
113
127
|
|
|
114
128
|
progress(e) {
|
|
115
|
-
|
|
116
|
-
|
|
129
|
+
const progressBarRect = this.$('.progress').getBoundingClientRect()
|
|
130
|
+
let clickX = e.clientX - progressBarRect.left
|
|
131
|
+
clickX = Math.max(0, Math.min(clickX, progressBarRect.width))
|
|
132
|
+
const offsetRatio = clickX / progressBarRect.width
|
|
133
|
+
|
|
134
|
+
this.video.currentTime = this.video.duration * offsetRatio
|
|
135
|
+
this.$('.now').innerHTML = getTimeStr(this.video.currentTime)
|
|
136
|
+
this.$('.current').style.width = offsetRatio * 100 + '%'
|
|
117
137
|
}
|
|
118
138
|
|
|
119
139
|
down(e) {
|
|
120
|
-
|
|
140
|
+
e.preventDefault()
|
|
121
141
|
this.moving = true
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
const progressBarRect = this.$('.progress').getBoundingClientRect()
|
|
143
|
+
this.progressBarWidth = progressBarRect.width
|
|
144
|
+
this.initialClientX = e.clientX
|
|
145
|
+
const initialOffsetRatio = this.video.currentTime / this.video.duration
|
|
146
|
+
this.initialOffsetPixels = initialOffsetRatio * this.progressBarWidth
|
|
147
|
+
|
|
148
|
+
document.addEventListener('pointermove', this.handleMove)
|
|
149
|
+
document.addEventListener('pointerup', this.handleUp, { once: true })
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
handleMove = (e) => {
|
|
153
|
+
if (!this.moving) return
|
|
154
|
+
|
|
155
|
+
const deltaX = e.clientX - this.initialClientX
|
|
156
|
+
let newOffsetPixels = this.initialOffsetPixels + deltaX
|
|
157
|
+
newOffsetPixels = Math.max(0, Math.min(newOffsetPixels, this.progressBarWidth))
|
|
158
|
+
|
|
159
|
+
this.$('.current').style.width = (newOffsetPixels / this.progressBarWidth) * 100 + '%'
|
|
160
|
+
|
|
161
|
+
const newTime = (newOffsetPixels / this.progressBarWidth) * this.video.duration
|
|
162
|
+
this.video.currentTime = Math.max(0, Math.min(newTime, this.video.duration))
|
|
163
|
+
|
|
164
|
+
this.$('.now').innerHTML = getTimeStr(this.video.currentTime)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
handleUp = (e) => {
|
|
168
|
+
this.moving = false
|
|
169
|
+
document.removeEventListener('pointermove', this.handleMove)
|
|
170
|
+
delete this.progressBarWidth
|
|
171
|
+
delete this.initialClientX
|
|
172
|
+
delete this.initialOffsetPixels
|
|
128
173
|
}
|
|
129
174
|
|
|
130
175
|
move(e) {
|
|
131
176
|
let offset = e.clientX - this.disX + 12
|
|
132
177
|
if (offset < 0) offset = 0
|
|
133
178
|
if (offset > this.$('.progress').clientWidth) {
|
|
134
|
-
|
|
179
|
+
offset = this.$('.progress').clientWidth
|
|
135
180
|
}
|
|
136
181
|
this.$('.current').style.width = offset + 'px'
|
|
137
182
|
this.video.currentTime = (offset / this.$('.progress').clientWidth) * this.video.duration
|
|
138
|
-
|
|
139
|
-
setTimeout((document.onpointermove = (e) => e && this.move(e)), 30)
|
|
183
|
+
this.$('.now').innerHTML = getTimeStr(this.video.currentTime)
|
|
140
184
|
}
|
|
141
185
|
|
|
142
186
|
alow() {
|
|
143
187
|
clearTimeout(this.timer)
|
|
144
188
|
this.$('.mark').style.cursor = 'default'
|
|
145
189
|
this.$('.eplayer').classList.add('hover')
|
|
146
|
-
this.
|
|
147
|
-
this
|
|
148
|
-
|
|
149
|
-
|
|
190
|
+
if (!this.cover) {
|
|
191
|
+
this.timer = setTimeout(() => {
|
|
192
|
+
this.$('.eplayer').classList.remove('hover')
|
|
193
|
+
}, 5000)
|
|
194
|
+
}
|
|
150
195
|
}
|
|
151
196
|
|
|
152
197
|
keydown(e) {
|
|
198
|
+
e.preventDefault()
|
|
153
199
|
switch (e.keyCode) {
|
|
154
|
-
case 37:
|
|
155
|
-
this.video.currentTime
|
|
200
|
+
case 37: // 左箭头 - 后退10秒
|
|
201
|
+
this.video.currentTime = Math.max(0, this.video.currentTime - 10)
|
|
156
202
|
break
|
|
157
|
-
case 39:
|
|
158
|
-
this.
|
|
203
|
+
case 39: // 右箭头 - 前进10秒 (支持长按3倍速)
|
|
204
|
+
if (!this.isRightKeyPressed) {
|
|
205
|
+
this.isRightKeyPressed = true
|
|
206
|
+
this.rightKeyPressTime = Date.now()
|
|
207
|
+
this.originalPlaybackRate = this.video.playbackRate
|
|
208
|
+
|
|
209
|
+
// 设置定时器,如果持续按住超过500ms则开启3倍速
|
|
210
|
+
this.rightKeyHoldTimer = setTimeout(() => {
|
|
211
|
+
this.isSpeedModeActive = true
|
|
212
|
+
this.video.playbackRate = 3
|
|
213
|
+
this.$('.speed').innerText = '3x'
|
|
214
|
+
this.$('.speed-indicator').style.display = 'block'
|
|
215
|
+
}, 500)
|
|
216
|
+
}
|
|
159
217
|
break
|
|
160
|
-
case 38:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
} catch (e) { }
|
|
218
|
+
case 38: // 上箭头 - 增加音量5%
|
|
219
|
+
e.preventDefault()
|
|
220
|
+
this.video.volume = Math.min(1, this.video.volume + 0.05)
|
|
164
221
|
break
|
|
165
|
-
case 40:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
} catch (e) { }
|
|
222
|
+
case 40: // 下箭头 - 减少音量5%
|
|
223
|
+
e.preventDefault()
|
|
224
|
+
this.video.volume = Math.max(0, this.video.volume - 0.05)
|
|
169
225
|
break
|
|
170
|
-
case 32:
|
|
226
|
+
case 32: // 空格键 - 播放/暂停
|
|
227
|
+
e.preventDefault()
|
|
171
228
|
this.play()
|
|
172
229
|
break
|
|
230
|
+
case 77: // M键 - 静音/取消静音
|
|
231
|
+
this.volume()
|
|
232
|
+
break
|
|
233
|
+
default:
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
keyup(e) {
|
|
238
|
+
switch (e.keyCode) {
|
|
239
|
+
case 39: // 右箭头松开
|
|
240
|
+
if (this.isRightKeyPressed) {
|
|
241
|
+
const pressDuration = Date.now() - this.rightKeyPressTime
|
|
242
|
+
this.isRightKeyPressed = false
|
|
243
|
+
|
|
244
|
+
// 清除定时器
|
|
245
|
+
if (this.rightKeyHoldTimer) {
|
|
246
|
+
clearTimeout(this.rightKeyHoldTimer)
|
|
247
|
+
this.rightKeyHoldTimer = null
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 判断是短按还是长按
|
|
251
|
+
if (pressDuration < 500 && !this.isSpeedModeActive) {
|
|
252
|
+
// 短按:只快进10秒
|
|
253
|
+
this.video.currentTime = Math.min(this.video.duration, this.video.currentTime + 10)
|
|
254
|
+
} else if (this.isSpeedModeActive) {
|
|
255
|
+
// 长按结束:恢复原播放速度并隐藏提示
|
|
256
|
+
this.video.playbackRate = this.originalPlaybackRate
|
|
257
|
+
this.$('.speed').innerText = this.originalPlaybackRate + 'x'
|
|
258
|
+
this.$('.speed-indicator').style.display = 'none'
|
|
259
|
+
this.isSpeedModeActive = false
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 重置状态
|
|
263
|
+
this.rightKeyPressTime = null
|
|
264
|
+
}
|
|
265
|
+
break
|
|
173
266
|
default:
|
|
174
267
|
}
|
|
175
268
|
}
|
|
@@ -242,12 +335,32 @@ class Eplayer extends HTMLElement {
|
|
|
242
335
|
list-style:none;
|
|
243
336
|
}
|
|
244
337
|
.eplayer,video{
|
|
245
|
-
|
|
338
|
+
font-family:'黑体';
|
|
246
339
|
height:100%;
|
|
247
340
|
width:100%;
|
|
248
341
|
color:var(--icons,rgba(255,255,255,0.6));
|
|
249
342
|
font-size:12px;
|
|
250
|
-
background
|
|
343
|
+
background:var(--bg,#000);
|
|
344
|
+
}
|
|
345
|
+
.eplayer .cover{
|
|
346
|
+
position: absolute;
|
|
347
|
+
z-index: 1;
|
|
348
|
+
top: 0;
|
|
349
|
+
left: 0;
|
|
350
|
+
right: 0;
|
|
351
|
+
bottom: 0;
|
|
352
|
+
background:url(${this.cover || ''}) center/cover no-repeat #fff;
|
|
353
|
+
filter:blur(8px);
|
|
354
|
+
}
|
|
355
|
+
.eplayer .cover-img{
|
|
356
|
+
position: absolute;
|
|
357
|
+
z-index: 1;
|
|
358
|
+
width:250px;
|
|
359
|
+
height:250px;
|
|
360
|
+
border-radius:125px;
|
|
361
|
+
left:50%;
|
|
362
|
+
top:50%;
|
|
363
|
+
transform:translate(-50%,-50%);
|
|
251
364
|
}
|
|
252
365
|
.eplayer{
|
|
253
366
|
user-select:none;
|
|
@@ -258,14 +371,17 @@ class Eplayer extends HTMLElement {
|
|
|
258
371
|
position:absolute;
|
|
259
372
|
left:0;
|
|
260
373
|
right:0;
|
|
261
|
-
bottom:0;
|
|
262
|
-
background:linear-gradient(transparent,rgba(0,0,0,.5));
|
|
263
|
-
transition: .3s ease-out;
|
|
264
374
|
bottom:-34px;
|
|
265
|
-
|
|
375
|
+
background:linear-gradient(transparent,rgba(0,0,0,.5));
|
|
376
|
+
transition: bottom .3s ease-out, opacity .3s ease-out;
|
|
377
|
+
opacity: 0;
|
|
378
|
+
pointer-events: none;
|
|
379
|
+
z-index:1000;
|
|
266
380
|
}
|
|
267
|
-
.hover
|
|
381
|
+
.hover .controls{
|
|
268
382
|
bottom:0;
|
|
383
|
+
opacity: 1;
|
|
384
|
+
pointer-events: auto;
|
|
269
385
|
}
|
|
270
386
|
.progress{
|
|
271
387
|
display:${this.live ? 'none' : 'block'};
|
|
@@ -392,11 +508,28 @@ class Eplayer extends HTMLElement {
|
|
|
392
508
|
bottom: 0;
|
|
393
509
|
pointer-events: none;
|
|
394
510
|
overflow: hidden;
|
|
395
|
-
z-index:
|
|
511
|
+
z-index: 0;
|
|
396
512
|
height:100%;
|
|
397
513
|
width:100%;
|
|
398
514
|
}
|
|
399
515
|
|
|
516
|
+
.speed-indicator {
|
|
517
|
+
position: absolute;
|
|
518
|
+
top: 20px;
|
|
519
|
+
left: 50%;
|
|
520
|
+
transform: translateX(-50%);
|
|
521
|
+
background: rgba(148, 108, 230, 0.9);
|
|
522
|
+
color: white;
|
|
523
|
+
padding: 8px 16px;
|
|
524
|
+
border-radius: 20px;
|
|
525
|
+
font-size: 14px;
|
|
526
|
+
font-weight: bold;
|
|
527
|
+
z-index: 999;
|
|
528
|
+
display: none;
|
|
529
|
+
pointer-events: none;
|
|
530
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
531
|
+
}
|
|
532
|
+
|
|
400
533
|
iconpark-icon{
|
|
401
534
|
margin-right:5px;
|
|
402
535
|
cursor:pointer;
|
|
@@ -416,7 +549,10 @@ class Eplayer extends HTMLElement {
|
|
|
416
549
|
<div class="eplayer hover">
|
|
417
550
|
<div class="danmaku"></div>
|
|
418
551
|
<video id="video" class="video" src="${this.src || ''}"></video>
|
|
552
|
+
<div class="cover"></div>
|
|
553
|
+
<img src="${this.cover || ''}" class="cover-img"/>
|
|
419
554
|
<div class="mark loading"></div>
|
|
555
|
+
<div class="speed-indicator">倍速中</div>
|
|
420
556
|
<div class="controls">
|
|
421
557
|
<div class="progress">
|
|
422
558
|
<b class="bg"></b>
|
|
@@ -433,7 +569,7 @@ class Eplayer extends HTMLElement {
|
|
|
433
569
|
</span>
|
|
434
570
|
</div>
|
|
435
571
|
<div class="right">
|
|
436
|
-
<em class="speed"
|
|
572
|
+
<em class="speed">1x</em>
|
|
437
573
|
<em class="pip">画中画</em>
|
|
438
574
|
<iconpark-icon icon-id="volume-ok" size="2rem" class="is-volume"></iconpark-icon>
|
|
439
575
|
<iconpark-icon icon-id="web-fullscreen" size="2rem"></iconpark-icon>
|
|
@@ -472,23 +608,14 @@ class Eplayer extends HTMLElement {
|
|
|
472
608
|
'.panel',
|
|
473
609
|
'.speed',
|
|
474
610
|
'.pip',
|
|
475
|
-
'.danmaku'
|
|
611
|
+
'.danmaku',
|
|
612
|
+
'.speed-indicator'
|
|
476
613
|
]
|
|
477
614
|
|
|
478
615
|
for (const key of doms) {
|
|
479
616
|
let dom = this.shadowRoot.querySelectorAll(key)
|
|
480
617
|
this.doms[key] = dom.length > 1 ? [...dom] : dom[0]
|
|
481
618
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
for (const name in Eplayer.plugins) {
|
|
485
|
-
const cb = Eplayer.plugins[name]
|
|
486
|
-
let node = document.createElement('li')
|
|
487
|
-
node.innerText = name
|
|
488
|
-
let panel = this.$('.panel')
|
|
489
|
-
panel.appendChild(node)
|
|
490
|
-
node.addEventListener('click', () => cb(this.shadowRoot))
|
|
491
|
-
}
|
|
492
619
|
}
|
|
493
620
|
|
|
494
621
|
connectedCallback() {
|
|
@@ -510,6 +637,7 @@ class Eplayer extends HTMLElement {
|
|
|
510
637
|
'.speed': this.speed,
|
|
511
638
|
'.bg': this.progress,
|
|
512
639
|
'.buffer': this.progress,
|
|
640
|
+
'.current': this.progress,
|
|
513
641
|
'.pip': this.pip,
|
|
514
642
|
})
|
|
515
643
|
this.delegate('pointerdown', {
|
|
@@ -522,9 +650,33 @@ class Eplayer extends HTMLElement {
|
|
|
522
650
|
this.full()
|
|
523
651
|
},
|
|
524
652
|
})
|
|
525
|
-
|
|
653
|
+
|
|
654
|
+
// 使用全局键盘监听以确保按键事件能在任何地方被捕获
|
|
655
|
+
this.keydownHandler = this.keydown.bind(this)
|
|
656
|
+
this.keyupHandler = this.keyup.bind(this)
|
|
657
|
+
document.addEventListener('keydown', this.keydownHandler)
|
|
658
|
+
document.addEventListener('keyup', this.keyupHandler)
|
|
659
|
+
|
|
526
660
|
this.delegate('mousemove', this.alow)
|
|
527
|
-
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
disconnectedCallback() {
|
|
664
|
+
// 清理全局键盘事件监听器
|
|
665
|
+
if (this.keydownHandler) {
|
|
666
|
+
document.removeEventListener('keydown', this.keydownHandler)
|
|
667
|
+
}
|
|
668
|
+
if (this.keyupHandler) {
|
|
669
|
+
document.removeEventListener('keyup', this.keyupHandler)
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// 清理长按定时器和状态
|
|
673
|
+
if (this.rightKeyHoldTimer) {
|
|
674
|
+
clearTimeout(this.rightKeyHoldTimer)
|
|
675
|
+
this.rightKeyHoldTimer = null
|
|
676
|
+
}
|
|
677
|
+
this.isRightKeyPressed = false
|
|
678
|
+
this.isSpeedModeActive = false
|
|
679
|
+
this.rightKeyPressTime = null
|
|
528
680
|
}
|
|
529
681
|
|
|
530
682
|
delegate(type, map) {
|
|
@@ -546,14 +698,20 @@ class Eplayer extends HTMLElement {
|
|
|
546
698
|
}
|
|
547
699
|
}
|
|
548
700
|
|
|
701
|
+
emit(name) {
|
|
702
|
+
const fn = Eplayer.subs[name]
|
|
703
|
+
fn && fn.call(this, this.shadowRoot)
|
|
704
|
+
}
|
|
705
|
+
|
|
549
706
|
}
|
|
550
707
|
|
|
551
|
-
Eplayer.
|
|
708
|
+
Eplayer.subs = {}
|
|
552
709
|
|
|
553
710
|
Eplayer.use = function (name, cb) {
|
|
554
|
-
this.
|
|
711
|
+
this.subs[name] = cb
|
|
555
712
|
}
|
|
556
713
|
|
|
714
|
+
|
|
557
715
|
function getTimeStr(time) {
|
|
558
716
|
let h = Math.floor(time / 3600)
|
|
559
717
|
let m = Math.floor((time % 3600) / 60)
|
|
@@ -574,8 +732,4 @@ function isFullScreen() {
|
|
|
574
732
|
document.head.appendChild(link)
|
|
575
733
|
})()
|
|
576
734
|
|
|
577
|
-
Eplayer.use('github源码', (ep) => {
|
|
578
|
-
window.location.href = 'https://github.com/132yse/eplayer'
|
|
579
|
-
})
|
|
580
|
-
|
|
581
735
|
customElements.define('e-player', Eplayer)
|
package/docs/index.html
CHANGED
|
@@ -57,11 +57,16 @@
|
|
|
57
57
|
.wrapper a:nth-child(3) {
|
|
58
58
|
background: #1ea6e9;
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
e-player {
|
|
62
|
+
--bg:#fff
|
|
63
|
+
}
|
|
60
64
|
</style>
|
|
61
65
|
|
|
62
66
|
<div class="wrapper">
|
|
63
67
|
<e-player id="ep"
|
|
64
|
-
src="https://
|
|
68
|
+
src="https://aod.cos.tx.xmcdn.com/storages/9976-audiofreehighqps/C9/1C/GAqhF9kMsE7kACAAAAQZZzo_.wav"
|
|
69
|
+
cover="https://dd-static.jd.com/ddimgp/jfs/t20261103/331442/3/18576/2295463/68da8cdcF3f9f05fd/790caba1cab6753d.png">
|
|
65
70
|
</e-player>
|
|
66
71
|
</div>
|
|
67
72
|
<script src="https://unpkg.com/@webcomponents/webcomponentsjs"></script>
|