@grfzhl/vue-hls-player 1.0.8 → 1.0.11

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/README.md CHANGED
@@ -183,6 +183,10 @@ it makes the video muted
183
183
  it will set the native <video> autoplay property
184
184
 
185
185
  ### Last release:
186
+ v1.0.9
187
+ - Fix sizes in fullscreen mode for video
188
+ - Hide transcript block completely when hidden
189
+
186
190
  v1.0.8
187
191
  - Add slots to inject own elements nearby video element
188
192
  - Add prop for autoplay video
@@ -1,8 +1,13 @@
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>
4
9
  <slot name="before-media"></slot>
5
- <media-theme-sutro class="video-player-theme-container">
10
+ <media-theme-sutro class="video-player-theme-container" :class="{'is-fullscreen': isFullscreen}">
6
11
  <video
7
12
  class="hls-player"
8
13
  slot="media"
@@ -58,6 +63,10 @@ import 'player.style/sutro';
58
63
  import SubtitleBlock from './SubtitleBlock.vue';
59
64
 
60
65
  const props = defineProps({
66
+ introTitle: {
67
+ type: String,
68
+ default: ''
69
+ },
61
70
  previewImageLink: {
62
71
  type: String,
63
72
  default: ''
@@ -111,6 +120,8 @@ const subtitlesContainer = ref(null)
111
120
  const currentSubtitleLang = ref(null)
112
121
  const videoCursor = ref(0)
113
122
  const isFullscreen = ref(false);
123
+ const orientation = ref(null)
124
+ const autoHideIntroTitle = ref(false);
114
125
 
115
126
  const videoElement = defineModel()
116
127
 
@@ -125,6 +136,21 @@ onMounted(() => {
125
136
 
126
137
  video.value.addEventListener('timeupdate', updateCurrentTime);
127
138
  document.addEventListener('fullscreenchange', onFullscreenChange);
139
+ document.addEventListener('orientationchange', onOrientationChange);
140
+ window.screen.orientation.addEventListener("change", onOrientationChange);
141
+
142
+ /**
143
+ * detect initial display orientation
144
+ */
145
+ if (typeof window.orientation === "undefined") {
146
+ orientation.value = window.screen.orientation.angle === 0 || window.screen.orientation.angle === 180
147
+ ? "portrait"
148
+ : "landscape";
149
+ } else {
150
+ orientation.value = window.orientation === 0 || window.orientation === 180
151
+ ? "portrait"
152
+ : "landscape"; // for safari
153
+ }
128
154
 
129
155
  /**
130
156
  * overwrite player.style video fullscreen button
@@ -136,11 +162,11 @@ onMounted(() => {
136
162
  if (mediaTheme && mediaTheme.shadowRoot) {
137
163
  const fullscreenButton = mediaTheme.shadowRoot.querySelector('media-fullscreen-button');
138
164
  if (fullscreenButton) {
139
- fullscreenButton.handleClick = (event) => {
165
+ fullscreenButton.handleClick = async (event) => {
140
166
  event.preventDefault();
141
167
  event.stopPropagation();
142
168
  event.stopImmediatePropagation();
143
- emit('video-fullscreen-action', event)
169
+ enterFullscreen(event)
144
170
  }
145
171
  observer.disconnect();
146
172
  } else {
@@ -162,6 +188,8 @@ onUnmounted(() => {
162
188
  if (video.value) {
163
189
  video.value.removeEventListener('timeupdate', updateCurrentTime);
164
190
  document.removeEventListener('fullscreenchange', onFullscreenChange);
191
+ document.removeEventListener('orientationchange', onOrientationChange);
192
+ window.screen.orientation.addEventListener("change", onOrientationChange);
165
193
  }
166
194
  });
167
195
 
@@ -191,9 +219,35 @@ watch([props, videoElement], (a) => {
191
219
  })
192
220
 
193
221
  function onFullscreenChange() {
222
+ isFullscreen.value = !!document.fullscreenElement
194
223
  emit('video-fullscreen-change', document.fullscreenElement)
224
+
225
+ // hide intro title after x seconds
226
+ if(isFullscreen.value === true) {
227
+ setTimeout(() => {
228
+ autoHideIntroTitle.value = true;
229
+ }, 5000)
230
+ } else {
231
+ autoHideIntroTitle.value = false;
232
+ }
195
233
  };
196
234
 
235
+ function onOrientationChange(e) {
236
+ let angle;
237
+ if (e.target && e.target.screen && e.target.screen.orientation) {
238
+ angle = e.target.screen.orientation.angle;
239
+ } else if (typeof window.orientation !== "undefined") {
240
+ // extra sausage for safari
241
+ angle = window.orientation;
242
+ }
243
+ orientation.value = angle === 0 || angle === 180
244
+ ? "portrait"
245
+ : "landscape";
246
+ }
247
+
248
+ function enterFullscreen(event) {
249
+ emit('video-fullscreen-action', event)
250
+ }
197
251
 
198
252
  function updateCurrentTime() {
199
253
  videoCursor.value = video.value.currentTime;
@@ -307,9 +361,47 @@ function changeSpeed(e) {
307
361
 
308
362
  .video-player-theme-container, .hls-player {
309
363
  width: 100%;
364
+ height: 100%;
310
365
  }
311
366
 
312
367
  .video-container {
313
368
  position: relative;
369
+ line-height: 0;
370
+ }
371
+ .media-fullscreen-overlay {
372
+ display: none;
373
+ position: fixed;
374
+ top: 0;
375
+ left: 0;
376
+ width: 100vw;
377
+ z-index: 9999999;
378
+ padding: 2rem 5rem;
379
+ }
380
+ .is-fullscreen .media-fullscreen-overlay {
381
+ display: block!important;
382
+ }
383
+ .intro-title h2 {
384
+ font-size: 23px;
385
+ color: white;
386
+ opacity: 1;
387
+ }
388
+ .fullscreen-video .media-container {
389
+ }
390
+ .video-player-theme-container.is-fullscreen {
391
+ width: 100vw;
392
+ height: 100vh;
393
+ object-fit: cover;
394
+ }
395
+ .video-player-theme-container.is-fullscreen .hls-player {
396
+ width: 100vw;
397
+ height: 100vh;
398
+ object-fit: cover;
399
+ }
400
+
401
+ .auto-hide {
402
+ opacity: 0;
403
+ -webkit-transition: opacity 1.5s ease-in-out;
404
+ -moz-transition: opacity 1.5s ease-in-out;
405
+ transition: opacity 1.5s ease-in-out;
314
406
  }
315
407
  </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="transcript-container" ref="subtitlesContainer">
2
+ <div class="transcript-container" ref="subtitlesContainer" v-if="showTranscriptBlock">
3
3
  <div class="transcript-toggle">
4
4
  <button data-headlessui-state="open" @click="toggleTranscript()">
5
5
  <div class="icon">
@@ -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.8",
4
+ "version": "1.0.11",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"