Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

🎯 preface

Video playback may not be much in daily business scenarios, but it is definitely not strange, choose a good plug-in often get twice the result with half the effort. Today, I will present a scenario to introduce bytedance’s open source watermelon player, which has many powerful functions 😎.

This article uses Vue+Xgplayer

🎯 Expected Effect

Watermelon videos have this preview effect (many video sites have it), and that’s what we’re going to do today

🎯 Final Effect

Xgplayer is easy to use

Install xgplayer

    npm install xgplayer
Copy the code

Import and initialize the required VUE components


import Player from 'xgplayer'
let player = new Player({
        id:' ' ,            // The id of the tag or use the el:dom element
        url: video url,videoInit: true.poster: Cover art,controls: false.playbackRate: [0.5.0.75.1.1.5.2].whitelist: [
        ' '].fluid: false.// download: true,
        width: '100%'.height: '200px'
    })
Copy the code

This creates a video player that can be created in the specified container.

🎯 Implementation Idea

In the full effect above, this case is obviously looping out multiple containers. Here we need to consider the problem of creating one or more Player instances. There are two ways of thinking about this, and this article uses the first one. By the way, in real business, data comes from interface services (the pit is here).

1. Create multiple containers in a loop and create instances for each container. To avoid this, use pagination.

2. Circular create container, do not create an instance, only show the cover, when moving into the container to destroy the previous instance, create the current instance (better solution), readers can try.

According to the effect, it is not difficult to see that the video is playing when moving into the container, and the current video is paused when moving out, so that only one is playing at the same time. I have prepared an IMG cover layer and a video layer, the default display image layer, using two events mouseEnter and mouseleave to dynamically control the display and hide of the corresponding container (there is also a pit), and the corresponding index instance operation (pause, destroy, etc.).

    startPlay(data,index){
        this.$refs['img'+index][0].style.display="none"
        this.$refs['video'+index][0].style.display="block"
        this.$nextTick(() = >{
            this.dom[index].play()
        })
    },

    move(data,index){
        this.$refs['img'+index][0].style.display="block"
        setTimeout(() = > {
            this.dom[index].pause()    
        }, 0);
        this.$refs['video'+index][0].style.display="none"
    },
Copy the code

🎯 Full code

Copy the code
<template>
 <div class="video">
     <div class="video-content" id="videoScroll" ref="videoScrollBar">
        <div  class="card"    v-for="(item,index) in videoList" :key="index"   >
                <div style="width:100%; height:200px" 
                    @mouseenter="startPlay(item,index)"
                    @mouseleave="move(item,index)">
                    <div                     
                        :ref="`img${index}`"
                        style="width:100%; height:200px; background-size: cover;" 
                        :style="{'background-image':`url(${item.spsltlj+'/'+item.spslt}) `}">
                    </div>
                    <div  style="display:none; overflow:hidden"   :ref="`video${index}`">
                    </div>
                 </div>
            <div class="title">
                {{item.spmc}}
            </div>
         </div>
     </div>
 </div>
</template>
 
<script>
import Player from 'xgplayer'
import { loadVideoList } from "@/api/video"
export default {
 name: 'Video'.components: {
    TitleField: Title
  },
 data () {
    return {
        videoList: [].dom: [].}},created() {
     this.setBaseList()
 },
 mounted(){},methods: {
   async setBaseList(){
        const res =await loadVideoList(this.form)
        this.videoList=res.data.records
        setTimeout(() = > {
            if(this.videoList.length){
                     this.videoList.forEach((item,index) = >{
                        this.init(item,index)
                },1000)}else{
               this.dom.length=0
            }
       })
    },

    init (data,index) {
            this.dom[index]= new Player({
            el: this.$refs['video'+index][0].url: data.splj+'/'+data.spbh,
            videoInit: true.poster:data.spsltlj+'/'+data.spslt,
            // cssFullscreen: true,
            lang: 'zh-cn'.controls: false.playbackRate: [0.5.0.75.1.1.5.2].whitelist: [
            ' '].ignores: ['play'].fluid: false.// download: true,
            width: '100%'.height: '200px'})},startPlay(data,index){
        this.$refs['img'+index][0].style.display="none"
        this.$refs['video'+index][0].style.display="block"
        this.$nextTick(() = >{
            this.dom[index].play()
        })
    },

    move(data,index){
        this.$refs['img'+index][0].style.display="block"
        setTimeout(() = > {
            this.dom[index].pause()    
        }, 0);
        this.$refs['video'+index][0].style.display="none"}}},</script>
 
<style scoped lang = "less">
    .card{
      width: 18%;
      margin: 0 20px 20px 0;
      float: left;
    }
     .title{
         width: 100%;
         color: # 000;
         height:40px;
         line-height: 40px;
         background-color: #ffffff;
         font-weight: 600;
         padding-left: 10px;
     }
</style>
Copy the code

🎯 Two pits

🫀 problem with initializing instances before data has been loaded

Here, the timer is used for delayed execution. If the loop is directly circulated, the watermelon player will report an error when playing, which basically means that the instance has not been initialized. Similarly, the play method should be called to play the event after dom loading is completed.

   async setBaseList(){
        const res =await loadVideoList(this.form)
        this.videoList=res.data.records
        setTimeout(() = > {
            if(this.videoList.length){
                 this.videoList.forEach((item,index) = >{
                      this.init(item,index)   // Initialize the video instance
                 },1000)}else{
                 this.dom.length=0}})},Copy the code

🫀 mouseenter and mouseleave

When using the V-for loop, mouseEnter and mouseleave are added to the parent element.

 <div  class="card"  v-for="(item,index) in videoList" :key="index"   >
     <div style="width:100%; height:200px" 
        @mouseenter="startPlay(item,index)"
        @mouseleave="move(item,index)">
        <div                     
            :ref="`img${index}`"
            style="width:100%; height:200px; background-size: cover;" 
            :style="{'background-image':`url(${item.spsltlj+'/'+item.spslt}) `}">
        </div>
        <div  style="display:none; overflow:hidden"   :ref="`video${index}`">
        </div>
   </div>
    <div class="title">
        {{item.spmc}}
    </div>
</div>
Copy the code

🎯 summary

The above is a simple demo of watermelon video, more powerful functions can be consulted on the official website, such as bullet screen, painting in painting, and so on are used, not only can be used in THE PC side, but also can be used in the mobile side.