Skip to content

Instantly share code, notes, and snippets.

@icalvo
Last active October 24, 2024 07:20
Show Gist options
  • Save icalvo/4e46895ed3c78576c0293bff767361b9 to your computer and use it in GitHub Desktop.
Save icalvo/4e46895ed3c78576c0293bff767361b9 to your computer and use it in GitHub Desktop.
Vue 3 video player component with Plyr, loads only once it's visible on its viewport
<script setup lang="ts">
import { ref, useTemplateRef, watch } from 'vue';
import Plyr from 'plyr';
import { useIntersectionObserver } from '@vueuse/core'
const props = defineProps<{
src: string
poster?: string
time?: number
}>()
const player = ref<Plyr | null>(null)
const videoElement = useTemplateRef('videoElement')
// Detects that the video is visible with Intersection Observer API
// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
// https://vueuse.org/core/useIntersectionObserver/
useIntersectionObserver(
videoElement,
([{ isIntersecting }]) => {
if (isIntersecting && videoElement.value != null && player.value == null) {
videoElement.value.load()
player.value = new Plyr(videoElement.value)
}
},
)
// Can jump to time by setting time prop
watch(() => props.time, (time?: number) => {
if (time && player.value)
{
player.value.currentTime = time
player.value.play()
}
})
</script>
<template>
<!-- The key here is preload="none" to avoid loading the video as it is created in the DOM. -->
<video ref="videoElement" width="320" height="240" playsinline controls preload="none" :poster>
<source :src type="video/mp4">
Your browser does not support the video tag.
</video>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment