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 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 === 'danma') {
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
- let offset = e.offsetX / this.$('.progress').offsetWidth
116
- this.video.currentTime = this.video.duration * offset
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
- this.disX = e.clientX - this.$('.dot').offsetLeft
140
+ e.preventDefault()
121
141
  this.moving = true
122
- document.onpointermove = (e) => this.move(e)
123
- document.onpointerup = () => {
124
- this.moveing = false
125
- document.onpointermove = null
126
- document.onpointerup = null
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
- this.offset = this.$('.progress').clientWidth
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
- document.onpointermove = null
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.timer = setTimeout(() => {
147
- this.$('.eplayer').classList.remove('hover')
148
- this.$('.mark').style.cursor = 'none'
149
- }, 5000)
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 -= 10
200
+ case 37: // 左箭头 - 后退10秒
201
+ this.video.currentTime = Math.max(0, this.video.currentTime - 10)
156
202
  break
157
- case 39:
158
- this.video.currentTime += 10
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
- try {
162
- this.video.volume = parseInt(this.video.volume * 100) / 100 + 0.05
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
- try {
167
- this.video.volume = parseInt(this.video.volume * 100) / 100 - 0.05
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
- font-family:'黑体';
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:#000
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
- z-index:1;
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:hover .controls{
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: 999;
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">倍速</em>
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
- this.delegate('keydown', this.keydown)
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
- this.$('.eplayer').oncontextmenu = () => false
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.plugins = {}
708
+ Eplayer.subs = {}
552
709
 
553
710
  Eplayer.use = function (name, cb) {
554
- this.plugins[name] = cb
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://a1.alibabausercontent.com/prod/feupload/user/edos8/2f0e7af0-29f1-11ef-b3cd-818e64ac843d.mp4">
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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eplayer",
3
- "version": "1.6.5",
3
+ "version": "1.6.8",
4
4
  "description": "A web-components html5 video player facing future",
5
5
  "main": "./docs/eplayer.js",
6
6
  "module": "./docs/eplayer.js",