eplayer 1.6.7 → 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,10 +4,18 @@ 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
9
10
  this.subs = []
10
11
 
12
+ // 添加长按右箭头3倍速相关状态
13
+ this.rightKeyHoldTimer = null
14
+ this.rightKeyPressTime = null
15
+ this.originalPlaybackRate = 1
16
+ this.isRightKeyPressed = false
17
+ this.isSpeedModeActive = false
18
+
11
19
  this.init()
12
20
  this.stream()
13
21
  }
@@ -37,11 +45,14 @@ class Eplayer extends HTMLElement {
37
45
  this.$('.time').style.display = 'inline-block'
38
46
  }
39
47
  }
40
- if (name === 'danma') {
48
+ if (name === 'danmu') {
41
49
  this.danmaku.add({
42
50
  msg: newVal
43
51
  })
44
52
  }
53
+ if (name === 'cover') {
54
+ this.cover = newVal
55
+ }
45
56
  }
46
57
 
47
58
  $(key) {
@@ -115,64 +126,143 @@ class Eplayer extends HTMLElement {
115
126
  }
116
127
 
117
128
  progress(e) {
118
- let offset = e.offsetX / this.$('.progress').offsetWidth
119
- 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 + '%'
120
137
  }
121
138
 
122
139
  down(e) {
123
- this.disX = e.clientX - this.$('.dot').offsetLeft
140
+ e.preventDefault()
124
141
  this.moving = true
125
- document.onpointermove = (e) => this.move(e)
126
- document.onpointerup = () => {
127
- this.moveing = false
128
- document.onpointermove = null
129
- document.onpointerup = null
130
- }
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
131
173
  }
132
174
 
133
175
  move(e) {
134
176
  let offset = e.clientX - this.disX + 12
135
177
  if (offset < 0) offset = 0
136
178
  if (offset > this.$('.progress').clientWidth) {
137
- this.offset = this.$('.progress').clientWidth
179
+ offset = this.$('.progress').clientWidth
138
180
  }
139
181
  this.$('.current').style.width = offset + 'px'
140
182
  this.video.currentTime = (offset / this.$('.progress').clientWidth) * this.video.duration
141
- document.onpointermove = null
142
- setTimeout((document.onpointermove = (e) => e && this.move(e)), 30)
183
+ this.$('.now').innerHTML = getTimeStr(this.video.currentTime)
143
184
  }
144
185
 
145
186
  alow() {
146
187
  clearTimeout(this.timer)
147
188
  this.$('.mark').style.cursor = 'default'
148
189
  this.$('.eplayer').classList.add('hover')
149
- this.timer = setTimeout(() => {
150
- this.$('.eplayer').classList.remove('hover')
151
- this.$('.mark').style.cursor = 'none'
152
- }, 5000)
190
+ if (!this.cover) {
191
+ this.timer = setTimeout(() => {
192
+ this.$('.eplayer').classList.remove('hover')
193
+ }, 5000)
194
+ }
153
195
  }
154
196
 
155
197
  keydown(e) {
198
+ e.preventDefault()
156
199
  switch (e.keyCode) {
157
- case 37:
158
- this.video.currentTime -= 10
200
+ case 37: // 左箭头 - 后退10秒
201
+ this.video.currentTime = Math.max(0, this.video.currentTime - 10)
159
202
  break
160
- case 39:
161
- 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
+ }
162
217
  break
163
- case 38:
164
- try {
165
- this.video.volume = parseInt(this.video.volume * 100) / 100 + 0.05
166
- } catch (e) { }
218
+ case 38: // 上箭头 - 增加音量5%
219
+ e.preventDefault()
220
+ this.video.volume = Math.min(1, this.video.volume + 0.05)
167
221
  break
168
- case 40:
169
- try {
170
- this.video.volume = parseInt(this.video.volume * 100) / 100 - 0.05
171
- } catch (e) { }
222
+ case 40: // 下箭头 - 减少音量5%
223
+ e.preventDefault()
224
+ this.video.volume = Math.max(0, this.video.volume - 0.05)
172
225
  break
173
- case 32:
226
+ case 32: // 空格键 - 播放/暂停
227
+ e.preventDefault()
174
228
  this.play()
175
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
176
266
  default:
177
267
  }
178
268
  }
@@ -245,12 +335,32 @@ class Eplayer extends HTMLElement {
245
335
  list-style:none;
246
336
  }
247
337
  .eplayer,video{
248
- font-family:'黑体';
338
+ font-family:'黑体';
249
339
  height:100%;
250
340
  width:100%;
251
341
  color:var(--icons,rgba(255,255,255,0.6));
252
342
  font-size:12px;
253
- 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%);
254
364
  }
255
365
  .eplayer{
256
366
  user-select:none;
@@ -261,14 +371,17 @@ class Eplayer extends HTMLElement {
261
371
  position:absolute;
262
372
  left:0;
263
373
  right:0;
264
- bottom:0;
265
- background:linear-gradient(transparent,rgba(0,0,0,.5));
266
- transition: .3s ease-out;
267
374
  bottom:-34px;
268
- 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;
269
380
  }
270
- .hover:hover .controls{
381
+ .hover .controls{
271
382
  bottom:0;
383
+ opacity: 1;
384
+ pointer-events: auto;
272
385
  }
273
386
  .progress{
274
387
  display:${this.live ? 'none' : 'block'};
@@ -395,11 +508,28 @@ class Eplayer extends HTMLElement {
395
508
  bottom: 0;
396
509
  pointer-events: none;
397
510
  overflow: hidden;
398
- z-index: 999;
511
+ z-index: 0;
399
512
  height:100%;
400
513
  width:100%;
401
514
  }
402
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
+
403
533
  iconpark-icon{
404
534
  margin-right:5px;
405
535
  cursor:pointer;
@@ -419,7 +549,10 @@ class Eplayer extends HTMLElement {
419
549
  <div class="eplayer hover">
420
550
  <div class="danmaku"></div>
421
551
  <video id="video" class="video" src="${this.src || ''}"></video>
552
+ <div class="cover"></div>
553
+ <img src="${this.cover || ''}" class="cover-img"/>
422
554
  <div class="mark loading"></div>
555
+ <div class="speed-indicator">倍速中</div>
423
556
  <div class="controls">
424
557
  <div class="progress">
425
558
  <b class="bg"></b>
@@ -436,7 +569,7 @@ class Eplayer extends HTMLElement {
436
569
  </span>
437
570
  </div>
438
571
  <div class="right">
439
- <em class="speed">倍速</em>
572
+ <em class="speed">1x</em>
440
573
  <em class="pip">画中画</em>
441
574
  <iconpark-icon icon-id="volume-ok" size="2rem" class="is-volume"></iconpark-icon>
442
575
  <iconpark-icon icon-id="web-fullscreen" size="2rem"></iconpark-icon>
@@ -475,7 +608,8 @@ class Eplayer extends HTMLElement {
475
608
  '.panel',
476
609
  '.speed',
477
610
  '.pip',
478
- '.danmaku'
611
+ '.danmaku',
612
+ '.speed-indicator'
479
613
  ]
480
614
 
481
615
  for (const key of doms) {
@@ -503,6 +637,7 @@ class Eplayer extends HTMLElement {
503
637
  '.speed': this.speed,
504
638
  '.bg': this.progress,
505
639
  '.buffer': this.progress,
640
+ '.current': this.progress,
506
641
  '.pip': this.pip,
507
642
  })
508
643
  this.delegate('pointerdown', {
@@ -515,10 +650,35 @@ class Eplayer extends HTMLElement {
515
650
  this.full()
516
651
  },
517
652
  })
518
- 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
+
519
660
  this.delegate('mousemove', this.alow)
520
661
  }
521
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
680
+ }
681
+
522
682
  delegate(type, map) {
523
683
  const that = this
524
684
  if (typeof map === 'function') {
@@ -538,7 +698,7 @@ class Eplayer extends HTMLElement {
538
698
  }
539
699
  }
540
700
 
541
- emit (name) {
701
+ emit(name) {
542
702
  const fn = Eplayer.subs[name]
543
703
  fn && fn.call(this, this.shadowRoot)
544
704
  }
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.7",
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",