Simple Vue Video Components with Video.js

by Anurak Sumranphan

HTML

<script src="https://vjs.zencdn.net/7.4.1/video.js"></script>
<link rel="stylesheet" href="https://vjs.zencdn.net/7.4.1/video-js.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/videojs-playlist.js"></script>
<div id="app">
  <div class="video-wrapper">
    <v-video
      src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
      aspectRatio="16:9"
      v-on:click="showMessage"
      loop
      ref="videojs"
    >
    </v-video>
  </div>
  <p v-if="show">
    This message will only be show when you click on the video.
  </p>
  <button v-on:click="play">
    Play
  </button>
  <button v-on:click="loadSrc">
    Change Video
  </button>
  <input v-model="source" type="text">
</div>

CSS

body {
  background: #1c2128;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #ffffff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

p,
.video-wrapper {
  margin-bottom: 16px;
}

.video-js {
  cursor: pointer;
  width: 100%;
}

Vue

Vue.component('v-video', {
  props: {
    src: String,
    autoplay: Boolean,
    controls: Boolean,
    loop: Boolean,
    aspectRatio: String
  },
  
  data: function () {
    return {
      $player: null
    }
  },
  
  methods: {
    _setup: function () {
      this.$player = videojs(this.$el)
      
      if (this.src) this.$player.src(this.src)
      if (this.autoplay) this.$player.autoplay(true)
      if (this.controls) this.$player.controls(true)
      if (this.loop) this.$player.loop(true)
      if (this.aspectRatio) this.$player.aspectRatio(this.aspectRatio)
      
      this.$player.on('click', () => this.$emit('click'))
      this.$player.on('play', () => this.$emit('play'))
      this.$player.on('playing', () => this.$emit('playing'))
      this.$player.on('pause', () => this.$emit('pause'))
    },
    loadSrc: function (source, autoplay = true) {
      //const currentSrc = this.$player.src()
    
      //if (source && currentSrc !== source) {
        this.$player.playlist(source)
        this.$player.playlist.autoadvance(0)
        
        if (autoplay) this.$player.autoplay(true)
      //}
    },
    play: function () {
      this.$player.play()
    }
  },
  
  mounted: function () {
    this.$nextTick(function () {
      this._setup()
    })
  },
  
  render: function (h) {
    return h('video', {
      class: 'video-js'
    })
  }
})

new Vue({
  el: "#app",
  
  data: function () {
    return {
      show: false,
      source: null,
      sources: [
      	{
          sources: [{
            src: 'http://techslides.com/demos/sample-videos/small.mp4',
            type: 'video/mp4'
          }]
        },
        {
          sources: [{
            src: 'https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4',
            type: 'video/mp4'
          }]
        }
      ]
    }
  },
  
  methods: {
    showMessage: function () {
      this.show = !this.show
    },
    play: function () {
      this.$refs.videojs.play()
    },
   ...