Vue video playback (Video)

1.vue2

The following properties can be customized:

Video file url (src), required, default ”, supports network address https and relative address require(‘…’)

Video cover url (poster), default ”, supports network address https and relative address require(‘…’)

When no cover is set, the frame corresponding to the second second of the video is automatically intercepted as the video cover (second). The default is 0.5s.

Video player width (width), default is 800px

Video player height (height), default is 450px

Whether to play the video immediately after it is ready (autoplay), the default is false

Whether to display controls to the user, such as whether to display controls to the user, such as progress bars, full screen, etc. (controls), the default is true

After the video playback is completed, whether to loop (loop), the default is false

Whether to mute (muted), the default is false

Whether to load the video after the page loads (preload). If the autoplay attribute is set, preload will be ignored. The default is auto // auto: Once the page loads, the video starts loading; metadata: Only the metadata of the video is loaded after the page loads. Data none: The video should not be loaded after the page loads

Whether to display the pause icon in the middle of the player (showPlay) when playback is paused, the default is true

The side length of the middle play pause button (playWidth), the default is 96px

The default scaling rule (zoom) of video poster for pictures and video content, the default is ‘contain’ // none: (default) save the original content without scaling; fill: do not maintain the original proportion, the content is stretched and filled The entire content container; contain: save the original proportion, and the content is scaled in a contained manner; cover: save the original proportion, and the content is scaled in a covering manner.

Note: To avoid conflict with the HTML5 native tag

Create the video playback component Video.vue:

<template>
  <div class="m-video" :class="{'u-video-hover': !hidden}" :style="`width: ${width}px; height: ${ height}px;`">
    <video
      ref="veo"
      :style="`object-fit: ${zoom};`"
      :src="src"
      :poster="veoPoster"
      :width="width"
      :height="height"
      :autoplay="autoplay"
      :controls="!originPlay & amp; & amp;controls"
      :loop="loop"
      :muted="autoplay || muted"
      :preload="preload"
      crossorigin="anonymous"
      @loadeddata="poster ? () => false : getPoster()"
      @pause="showPlay ? onPause() : () => false"
      @playing="showPlay ? onPlaying() : () => false"
      @click.prevent.once="onPlay"
      v-bind="$attrs">
      Your browser does not support the video tag.
    </video>
    <svg v-show="originPlay || showPlay" class="u-play" :class="{'hidden': hidden}" :style="`width: ${playWidth }px; height: ${playWidth}px;`" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4.75 6.75C4.75 5.64543 5.64543 4.75 6.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25 6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V6.75 Z"></path>
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 12L9.75 8.75V15.25L15.25 12Z">< /path>
    </svg>
  </div>
</template>
<script>
export default {
  name: 'Video',
  props: {
    src: { // Video file url, must be transmitted, supports network address https and relative address require('@/assets/files/Bao.mp4')
      type: String,
      required: true,
      default: ''
    },
    poster: { //Video cover url, supports network address https and relative address require('@/assets/images/Bao.jpg')
      type: String,
      default: ''
    },
    second: { // When no cover is set, automatically capture the frame corresponding to the second second of the video as the video cover
      type: Number,
      default: 0.5
    },
    width: { // Video player width
      type: Number,
      default: 800
    },
    height: { // Video player height
      type: Number,
      default: 450
    },
    /*
      Refer to MDN Autoplay Guide: https://developer.mozilla.org/zh-CN/docs/Web/Media/Autoplay_guide
      Autoplay function
      According to the new policy, media content will automatically play if at least one of the following conditions is met:
      1. The audio is muted or its volume is set to 0
      2. The user has interacted with the web page (including clicking, touching, pressing a key, etc.)
      3. The website has been whitelisted; this may happen automatically if the browser determines that the user frequently interacts with media, or it may happen manually through preferences or other user interface features
      4. Apply the autoplay policy to <iframe> or its document
      autoplay: Since currently in the latest version of Chrome browser (and all browsers based on Chromium),
      Autoplay of audio and video is no longer allowed. Even if you set the autoplay attribute for the video or audio tag, it still cannot play automatically!
      Solution: When setting video autoplay, the video must be set to muted muted: true to achieve automatic playback.
      Then the user can use the control bar to turn on the sound, similar to the logic of a promotional video that automatically plays for certain products.
    */
    autoplay: { // Whether to play the video immediately after it is ready
      type: Boolean,
      default: false
    },
    controls: { // Whether to display controls to the user, such as progress bar, full screen
      type: Boolean,
      default: true
    },
    loop: { // After the video playback is completed, whether to loop
      type: Boolean,
      default: false
    },
    muted: { // Whether to mute
      type: Boolean,
      default: false
    },
    preload: { // Whether to load the video after the page is loaded. If the autoplay attribute is set, preload will be ignored;
      type: String,
      default: 'auto' // auto: Once the page is loaded, start loading the video; metadata: When the page is loaded, only the metadata of the video is loaded none: The video should not be loaded after the page is loaded
    },
    showPlay: { // Whether to display the pause icon in the middle of the player when playback is paused
      type: Boolean,
      default: true
    },
    playWidth: { // Side length of the middle play pause button
      type: Number,
      default: 96
    },
    zoom: { // Video's poster's default picture and video content scaling rules
      type: String,
      default: 'contain' // none: (default) save the original content without scaling; fill: do not maintain the original proportion, the content is stretched to fill the entire content container; contain: save the original proportion, the content is included Zoom; cover: save the original proportion, and the content is scaled in a covering manner
    }
  },
  data () {
    return {
      veoPoster: this.poster,
      originPlay: true,
      hidden: false
    }
  },
  mounted () {
    if (this.autoplay) {
      this.hidden = true
      this.originPlay = false
    }
    /*
      Customize the playback speed, tested:
      Need to set in vue2: this.$refs.veo.playbackRate = 2
      Need to set in vue3: veo.value.defaultPlaybackRate = 2
    */
    // this.$refs.veo.playbackRate = 2
  },
  methods: {
    /*
      The loadeddata event is triggered after the video frame at the current playing position of the media (usually the first frame) is loaded.
      It will not trigger when preload is none
    */
    getPoster () { // When no cover is set, automatically obtain the frame corresponding to 0.5s of the video as the video cover
      // Since the first frame of many videos is a black screen, the video start playback time is set to 0.5s, that is, the frame at this time is used as the cover image
      this.$refs.veo.currentTime = this.second
      //Create canvas element
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      //canvas drawing
      canvas.width = this.$refs.veo.videoWidth
      canvas.height = this.$refs.veo.videoHeight
      ctx.drawImage(this.$refs.veo, 0, 0, canvas.width, canvas.height)
      // Convert canvas to base64 encoding format
      this.veoPoster = canvas.toDataURL('image/png')
    },
    onPlay () {
      if (this.originPlay) {
        this.$refs.veo.currentTime = 0
        this.originPlay = false
      }
      if (this.autoplay) {
        this.$refs.veo.pause()
      } else {
        this.hidden = true
        this.$refs.veo.play()
      }
    },
    onPause () {
      this.hidden = false
    },
    onPlaying () {
      this.hidden = true
    }
  }
}
</script>
<style lang="less" scoped>
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
.m-video {
  display: inline-block;
  position: relative;
  background: #000;
  cursor: pointer;
  .u-play {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
    fill: none;
    color: #FFF;
    pointer-events: none;
    opacity: 0.7;
    transition: opacity .3s;
    path {
      stroke: #FFF;
    }
  }
  .hidden {
    opacity: 0;
  }
}
.u-video-hover {
   & amp;:hover {
    .u-play {
      opacity: 0.9;
    }
  }
}
</style>

Introduce in the page you want to use:

<template>
  <div>
    <h2 class="mb10">Basic use of Video player</h2>
    <Video :src="src" :poster="poster" />
    <h2 class="mt30 mb10">Autoplay</h2>
    <Video autoplay :src="src" :poster="poster" />
    <h2 class="mt30 mb10">Automatically capture the specified frame of the video as the video cover</h2>
    <Video :src="src" :second="3" />
  </div>
</template>
<script>
import Video from 'components/Video'
export default {
  name: 'VideoPlay',
  components: {
    Video
  },
  data () {
    return {
      src: '',
      poster: ''
    }
  }
}
</script>

2.vue3

components

<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface Props {
  src: string //Video file address, supports network address https and relative address
  poster?: string //Video cover address, supports network address https and relative address
  second?: number // When no cover is set, automatically capture the frame corresponding to the second second of the video as the video cover.
  width?: number // Video player width, unit px
  height?: number // Video player height, unit px
  autoplay?: boolean // Whether to play the video immediately after it is ready, the priority is higher than preload
  controls?: boolean // Whether to display controls to the user, such as progress bar, full screen, etc.
  loop?: boolean // After the video playback is completed, whether to loop
  muted?: boolean // Whether to mute
  preload?: 'auto'|'metadata'|'none' // Whether to load the video after the page is loaded. If the autoplay attribute is set, preload will be ignored.
  showPlay?: boolean // Whether to display the pause icon in the middle of the player when playback is paused
  fit?: 'none'|'fill'|'contain'|'cover' // Video's poster default image and video content scaling rules
}
const props = withDefaults(defineProps<Props>(), {
  src: '',
  poster: '',
  second: 0.5,
  width: 800,
  height: 450,
  /*
    Refer to MDN Autoplay Guide: https://developer.mozilla.org/zh-CN/docs/Web/Media/Autoplay_guide
    Autoplay function
    According to the new policy, media content will automatically play if at least one of the following conditions is met:
    1. The audio is muted or its volume is set to 0
    2. The user has interacted with the web page (including clicking, touching, pressing a key, etc.)
    3. The website has been whitelisted; this may happen automatically if the browser determines that the user frequently interacts with media, or it may happen manually through preferences or other user interface features
    4. Apply the autoplay policy to <iframe> or its document
    autoplay: Since currently in the latest version of Chrome browser (and all browsers based on Chromium),
    Autoplay of audio and video is no longer allowed. Even if you set the autoplay attribute for the video or audio tag, it still cannot play automatically!
    Solution: When setting video autoplay, the video must be set to muted muted: true to achieve automatic playback.
    Then the user can use the control bar to turn on the sound, similar to the logic of a promotional video that automatically plays for certain products.
  */
  autoplay: false,
  controls: true,
  loop: false,
  muted: false,
  /*
    preload optional attributes:
    auto: Once the page loads, start loading the video;
    metadata: When the page is loaded, only the metadata of the video (such as length) is loaded. It is recommended to use metadata so that the video automatically obtains the first frame as the cover poster.
    none: The video should not be loaded after the page loads
  */
  preload: 'auto',
  showPlay: true,
  /*
    fit optional attributes:
    none: Save the original content without scaling;
    fill: The original proportion is not maintained, and the content is stretched to fill the entire content container;
    contain: Save the original proportion, and the content is scaled in a contained manner;
    cover: Save the original proportion, and the content is scaled in a covering manner
  */
  fit: 'contain'
})
// Reference documentation: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/video
const veoPoster = ref(props.poster)
const originPlay = ref(true)
const hidden = ref(false) // Whether to hide the play button in the middle of the player
// Annotate the type for the template reference
const veo = ref()
// const veo = ref<HTMLVideoElement | null>(null) // Declare a template reference with the same name
 
/*
  The loadeddata event is triggered after the video frame at the current playing position of the media (usually the first frame) is loaded.
  It will not trigger when preload is none
*/
function getPoster () { // When the cover is not set, automatically intercept the corresponding frame of 0.5s of the video as the video cover
  // Since the first frame of many videos is a black screen, the video start playback time is set to 0.5s, that is, the frame at this time is used as the cover image
  veo.value.currentTime = props.second
  //Create canvas element
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  //canvas drawing
  canvas.width = veo.value.videoWidth
  canvas.height = veo.value.videoHeight
  ctx?.drawImage(veo.value, 0, 0, canvas.width, canvas.height)
  // Convert canvas to base64 encoding format
  veoPoster.value = canvas.toDataURL('image/png')
}
function onPlay () {
  if (originPlay.value) {
    veo.value.currentTime = 0
    originPlay.value = false
  }
  if (props.autoplay) {
    veo.value?.pause()
  } else {
    hidden.value = true
    veo.value?.play()
  }
}
function onPause () {
  hidden.value = false
}
function onPlaying () {
  hidden.value = true
}
onMounted(() => {
  if (props.autoplay) {
    hidden.value = true
    originPlay.value = false
  }
  /*
    Customize the playback speed, tested:
    Need to set in vue2: this.$refs.veo.playbackRate = 2
    Need to set in vue3: veo.value.defaultPlaybackRate = 2
  */
  // veo.value.defaultPlaybackRate = 2
})
</script>
<template>
  <div class="m-video" :class="{'u-video-hover': !hidden}" :style="`width: ${width}px; height: ${ height}px;`">
    <video
      ref="veo"
      :style="`object-fit: ${fit};`"
      :src="src"
      :poster="veoPoster"
      :width="width"
      :height="height"
      :autoplay="autoplay"
      :controls="!originPlay & amp; & amp;controls"
      :loop="loop"
      :muted="autoplay || muted"
      :preload="preload"
      crossorigin="anonymous"
      @loadeddata="poster ? () => false : getPoster()"
      @pause="showPlay ? onPause() : () => false"
      @playing="showPlay ? onPlaying() : () => false"
      @click.prevent.once="onPlay"
      v-bind="$attrs">
      Your browser does not support the video tag.
    </video>
    <span v-show="originPlay || showPlay" class="m-icon-play" :class="{'hidden': hidden}">
      <svg class="u-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 34">
      <path d="M28.26,11.961L11.035,0.813C7.464-1.498,3,1.391,3,6.013v21.974c0,4.622,4.464,7.511,8.035,5.2L28.26,22.039
          C31.913,19.675,31.913,14.325,28.26,11.961z"></path>
      </svg>
    </span>
  </div>
</template>
<style lang="less" scoped>
.m-video {
  display: inline-block;
  position: relative;
  background: #000;
  cursor: pointer;
  .m-icon-play {
    display: inline-block;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: rgba(0,0,0,.7);
    pointer-events: none;
    opacity: 0.8;
    transition: opacity .3s;
    .u-svg {
      display: inline-block;
      fill: #FFF;
      width: 29px;
      height: 34px;
      margin-top: 23px;
      margin-left: 27px;
    }
  }
  .hidden {
    opacity: 0;
  }
}
.u-video-hover {
   & amp;:hover {
    .m-icon-play {
      opacity: 1;
    }
  }
}
</style>

Quote

<script setup lang="ts">
import Video from './Video.vue'
import { ref } from 'vue'
 
const src = ref('')
const poster = ref('')
</script>
 
<template>
  <div>
    <h2 class="mb10">Basic use of Video player</h2>
    <Video :src="src" :poster="poster" />
    <h2 class="mt30 mb10">Autoplay</h2>
    <Video autoplay :src="src" :poster="poster" />
    <h2 class="mt30 mb10">Automatically capture specified frames from the video as video cover</h2>
    <Video :src="src" :second="3" />
  </div>
</template>