@grfzhl/vue-hls-player 1.0.9 → 1.0.12

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.
@@ -1,6 +1,22 @@
1
1
  <template>
2
2
  <div class="video-container">
3
- <div class="media-container" id="hls-player-media-container">
3
+ <div class="media-container" id="hls-player-media-container" :class="{'is-fullscreen': isFullscreen}">
4
+ <div class="media-fullscreen-overlay" v-if="introTitle">
5
+ <div class="intro-title" :class="{ 'auto-hide': autoHideIntroTitle }">
6
+ <h2>{{ introTitle }}</h2>
7
+ </div>
8
+ </div>
9
+ <div class="media-overlay" v-if="initialPlayButton">
10
+ <div class="initial-play">
11
+ <media-play-button mediapaused="" class="media-button" aria-label="play" tabindex="0" role="button" @click="video.play()">
12
+ <svg slot="icon" viewBox="0 0 32 32">
13
+ <g>
14
+ <path id="icon-play" d="M20.7131 14.6976C21.7208 15.2735 21.7208 16.7265 20.7131 17.3024L12.7442 21.856C11.7442 22.4274 10.5 21.7054 10.5 20.5536L10.5 11.4464C10.5 10.2946 11.7442 9.57257 12.7442 10.144L20.7131 14.6976Z"></path>
15
+ </g>
16
+ </svg>
17
+ </media-play-button>
18
+ </div>
19
+ </div>
4
20
  <slot name="before-media"></slot>
5
21
  <media-theme-sutro class="video-player-theme-container" :class="{'is-fullscreen': isFullscreen}">
6
22
  <video
@@ -58,6 +74,10 @@ import 'player.style/sutro';
58
74
  import SubtitleBlock from './SubtitleBlock.vue';
59
75
 
60
76
  const props = defineProps({
77
+ introTitle: {
78
+ type: String,
79
+ default: ''
80
+ },
61
81
  previewImageLink: {
62
82
  type: String,
63
83
  default: ''
@@ -111,6 +131,9 @@ const subtitlesContainer = ref(null)
111
131
  const currentSubtitleLang = ref(null)
112
132
  const videoCursor = ref(0)
113
133
  const isFullscreen = ref(false);
134
+ const orientation = ref(null)
135
+ const autoHideIntroTitle = ref(false);
136
+ const initialPlayButton = ref(false);
114
137
 
115
138
  const videoElement = defineModel()
116
139
 
@@ -125,6 +148,25 @@ onMounted(() => {
125
148
 
126
149
  video.value.addEventListener('timeupdate', updateCurrentTime);
127
150
  document.addEventListener('fullscreenchange', onFullscreenChange);
151
+ document.addEventListener('orientationchange', onOrientationChange);
152
+ window.screen.orientation.addEventListener("change", onOrientationChange);
153
+
154
+ if(video.value.paused || video.value.currentTime === 0) {
155
+ initialPlayButton.value = true
156
+ }
157
+
158
+ /**
159
+ * detect initial display orientation
160
+ */
161
+ if (typeof window.orientation === "undefined") {
162
+ orientation.value = window.screen.orientation.angle === 0 || window.screen.orientation.angle === 180
163
+ ? "portrait"
164
+ : "landscape";
165
+ } else {
166
+ orientation.value = window.orientation === 0 || window.orientation === 180
167
+ ? "portrait"
168
+ : "landscape"; // for safari
169
+ }
128
170
 
129
171
  /**
130
172
  * overwrite player.style video fullscreen button
@@ -136,11 +178,11 @@ onMounted(() => {
136
178
  if (mediaTheme && mediaTheme.shadowRoot) {
137
179
  const fullscreenButton = mediaTheme.shadowRoot.querySelector('media-fullscreen-button');
138
180
  if (fullscreenButton) {
139
- fullscreenButton.handleClick = (event) => {
181
+ fullscreenButton.handleClick = async (event) => {
140
182
  event.preventDefault();
141
183
  event.stopPropagation();
142
184
  event.stopImmediatePropagation();
143
- emit('video-fullscreen-action', event)
185
+ enterFullscreen(event)
144
186
  }
145
187
  observer.disconnect();
146
188
  } else {
@@ -162,6 +204,8 @@ onUnmounted(() => {
162
204
  if (video.value) {
163
205
  video.value.removeEventListener('timeupdate', updateCurrentTime);
164
206
  document.removeEventListener('fullscreenchange', onFullscreenChange);
207
+ document.removeEventListener('orientationchange', onOrientationChange);
208
+ window.screen.orientation.addEventListener("change", onOrientationChange);
165
209
  }
166
210
  });
167
211
 
@@ -193,11 +237,39 @@ watch([props, videoElement], (a) => {
193
237
  function onFullscreenChange() {
194
238
  isFullscreen.value = !!document.fullscreenElement
195
239
  emit('video-fullscreen-change', document.fullscreenElement)
240
+
241
+ // hide intro title after x seconds
242
+ if(isFullscreen.value === true) {
243
+ setTimeout(() => {
244
+ autoHideIntroTitle.value = true;
245
+ }, 5000)
246
+ } else {
247
+ autoHideIntroTitle.value = false;
248
+ }
196
249
  };
197
250
 
251
+ function onOrientationChange(e) {
252
+ let angle;
253
+ if (e.target && e.target.screen && e.target.screen.orientation) {
254
+ angle = e.target.screen.orientation.angle;
255
+ } else if (typeof window.orientation !== "undefined") {
256
+ // extra sausage for safari
257
+ angle = window.orientation;
258
+ }
259
+ orientation.value = angle === 0 || angle === 180
260
+ ? "portrait"
261
+ : "landscape";
262
+ }
263
+
264
+ function enterFullscreen(event) {
265
+ emit('video-fullscreen-action', event)
266
+ }
198
267
 
199
268
  function updateCurrentTime() {
200
269
  videoCursor.value = video.value.currentTime;
270
+ if(!video.value.paused) {
271
+ initialPlayButton.value = false;
272
+ }
201
273
  }
202
274
 
203
275
  function toggleTranscript() {
@@ -315,7 +387,49 @@ function changeSpeed(e) {
315
387
  position: relative;
316
388
  line-height: 0;
317
389
  }
318
-
390
+ .media-overlay {
391
+ position: absolute;
392
+ height: calc(100% - 50px);
393
+ top: 0;
394
+ width: 100%;
395
+ z-index: 99;
396
+ background: linear-gradient(180deg, rgba(2,0,36,1) 0%, rgba(0,0,0,0) 100%);
397
+ }
398
+ .media-overlay .initial-play {
399
+ display: flex;
400
+ justify-content: center;
401
+ align-content: center;
402
+ align-items: center;
403
+ height: 100%;
404
+ }
405
+ .media-overlay .initial-play media-play-button {
406
+ width: 80px;
407
+ height: 80px;
408
+ border-radius: 10px;
409
+ }
410
+ .media-overlay .initial-play media-play-button svg {
411
+ width: 100%;
412
+ height: 100%;
413
+ }
414
+ .media-fullscreen-overlay {
415
+ display: none;
416
+ position: fixed;
417
+ top: 0;
418
+ left: 0;
419
+ width: 100vw;
420
+ z-index: 9999999;
421
+ padding: 2rem 5rem;
422
+ }
423
+ .is-fullscreen .media-fullscreen-overlay {
424
+ display: block!important;
425
+ }
426
+ .intro-title h2 {
427
+ font-size: 23px;
428
+ color: white;
429
+ opacity: 1;
430
+ }
431
+ .fullscreen-video .media-container {
432
+ }
319
433
  .video-player-theme-container.is-fullscreen {
320
434
  width: 100vw;
321
435
  height: 100vh;
@@ -326,4 +440,11 @@ function changeSpeed(e) {
326
440
  height: 100vh;
327
441
  object-fit: cover;
328
442
  }
443
+
444
+ .auto-hide {
445
+ opacity: 0;
446
+ -webkit-transition: opacity 1.5s ease-in-out;
447
+ -moz-transition: opacity 1.5s ease-in-out;
448
+ transition: opacity 1.5s ease-in-out;
449
+ }
329
450
  </style>
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <BasePlayer
3
+ :introTitle="introTitle"
3
4
  :previewImageLink="previewImageLink"
4
5
  :link="link"
5
6
  :progress="progress"
@@ -26,7 +27,7 @@
26
27
  import BasePlayer from './BasePlayer.vue'
27
28
  import { ref } from 'vue'
28
29
 
29
- const emit = defineEmits(['pause', 'video-ended', 'video-fullscreen-change'])
30
+ const emit = defineEmits(['pause', 'video-ended', 'video-fullscreen-change', 'video-fullscreen-action'])
30
31
 
31
32
  const videoElement = ref(null);
32
33
 
@@ -59,6 +60,10 @@ defineProps({
59
60
  type: Boolean,
60
61
  default: false
61
62
  },
63
+ introTitle: {
64
+ type: String,
65
+ default: ''
66
+ },
62
67
  showTranscriptBlock: {
63
68
  type: Boolean,
64
69
  default: true
@@ -5,6 +5,7 @@
5
5
  @video-fullscreen-change="onVideoFullScreenChange"
6
6
  @video-ended="onVideoEnd"
7
7
  @video-fullscreen-action="oVideoFullscreenAction"
8
+ :introTitle="introTitle"
8
9
  :previewImageLink="previewImageLink"
9
10
  :showTranscriptBlock="showTranscriptBlock"
10
11
  :isFullscreen="isFullscreen"
@@ -69,6 +70,10 @@ defineProps({
69
70
  type: Boolean,
70
71
  default: false
71
72
  },
73
+ introTitle: {
74
+ type: String,
75
+ default: ''
76
+ },
72
77
  showTranscriptBlock: {
73
78
  type: Boolean,
74
79
  default: true
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@grfzhl/vue-hls-player",
3
3
  "private": false,
4
- "version": "1.0.9",
4
+ "version": "1.0.12",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"