[前端] vue封装自定义播放器

一、使用icomoon

1.生成和下载图标相关文件

先使用icomoon获取我们要使用的图标,例如播放、暂停、停止、全屏等图标。

icomoon网站:https://icomoon.io/app/#/select

在其中选择我们需要的图标:

 然后点击右下角的 "Generate Font":

将我们图标的名字修改成自己想要的。

然后点击右下角的 "Download"。会帮我们下载一个zip压缩包。

解压,获取以下文件:

2.使用style.css

将style.css文件和fonts文件夹拷贝到项目中(路径自己决定):

在main.js中导入style.css:

import "./styles/style.css"

导入后,就可以使用图标了。

二、自定义播放器代码结构

1.基本代码结构

MyVideo.vue:

<template>
  <div class="video">
    <video>
      <source src="https://video.pearvideo.com/mp4/third/20200212/cont-1651180-11487675-112807-hd.mp4"/>
    </video>
    <div class="controls">
      <div class="con_left">
        <span class="icon-play"></span>
        <span class="icon-stop"></span>
        <span>00:00/10:00</span>
      </div>
      <div class="con_right">
        <span class="icon-volume"></span>
        <span class="icon-enlarge"></span>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "MyVideo",
  }
</script>

<style scoped>
  .video {
    position: relative;
  }
  .video video {
    width: 100%;
    height: 100%;
  }
  .controls {
    width: 100%;
    height: 40px;
    position: absolute;
    bottom: 0;
    left: 0;
    background-color: #99a9bf;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .controls span {
    padding: 0 5px;
    color: #fff;
  }
</style>

这是自定义播放器的基本代码结构,其中我们使用class指定了几个icomoon图标。

2.当前效果

三、实现controls中的各功能

<template>
  <div class="video" ref="video">
    <video ref="myvideo" @canplay="getTotalTime" @timeupdate="timeUpdate">
      <source :src="src"/>
    </video>
    <div class="controls">
      <div class="con_left">
        <span @click="togglePlay" :class="{'icon-play':isPaused,'icon-pause':!isPaused,'cursor':true}"></span>
        <span @click="stopPlay" class="icon-stop cursor"></span>
        <span>{{currentTime}}/{{totalTime}}</span>
      </div>
      <div class="con_right">
        <span @click="toggleMuted" :class="{'icon-volume':!isMuted,'icon-volume-mute':isMuted,'cursor':true}"></span>
        <span @click="toggleFullScreen"
              :class="{'icon-enlarge':!isFullScreen ,'icon-shrink':isFullScreen,'cursor':true}"></span>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "MyVideo",
    props: [
      'src'  // 这里接收父组件传来的src参数,视频的url
    ],
    data() {
      return {
        // 用于存放<video>标签对象,方便调用原生API
        myvideo: null,
        video: null,
        // 是否暂停,用于控制播放与暂停
        isPaused: true,
        // 播放当前时间
        currentTime: "00:00",
        totalTime: "00:00",
        // 声音是否静音
        isMuted: false,
        // 是否全屏
        isFullScreen: false,
      }
    },
    mounted() {
      // 加载完毕后,先获取<video>标签DOM对象
      this.myvideo = this.$refs.myvideo
      this.video = this.$refs.video
    },
    methods: {
      // 播放与暂停,注意,这里isPause的变化,对应图标的变化
      togglePlay() {
        this.isPaused = !this.isPaused;
        if (this.isPaused) {
          this.myvideo.pause()
        } else {
          this.myvideo.play()
        }
      },
      // 停止播放
      stopPlay() {
        this.myvideo.pause()
        this.myvideo.currentTime = 0
        // 停止播放了,要将播放图标从暂停切换到播放,isPaused为true的时候,图标是播放
        this.isPaused = true
      },
      // 定义一个时间处理函数,例如将100秒,处理成1:40
      timeFormat(time) {
        let minute = Math.floor((time % 3600) / 60);  // 取余
        let second = Math.floor(time % 60);
        minute = minute < 10 ? "0" + minute : minute;
        second = second < 10 ? "0" + second : second;
        return `${minute}:${second}`;
      },
      // 当事件oncanplay触发时,获取视频的总时间信息,然后通过timeFormat函数处理成00:00的格式,并渲染到template中
      getTotalTime() {
        this.currentTime = this.timeFormat(this.myvideo.currentTime);
        this.totalTime = this.timeFormat(this.myvideo.duration);
      },
      // 时间timeupdate触发时,更新当前播放时间
      timeUpdate() {
        this.currentTime = this.timeFormat(this.myvideo.currentTime)
      },
      // 声音是否静音
      toggleMuted() {
        this.isMuted = !this.isMuted
        this.myvideo.muted = !this.myvideo.muted
      },
      // 切换全屏,注意,这里进入全屏时,使用的元素是this.video,而不是this.myvideo。video是myvideo的父标签,这样控制条才能正确显示
      toggleFullScreen(event) {
        let fullscreen = document.webkitIsFullScreen || document.fullscreen;
        this.isFullScreen = fullscreen
        if (!this.isFullScreen) {
          this.isFullScreen = !this.isFullScreen
          const inFun = this.video.requestFullscreen || this.video.webkitRequestFullScreen;
          inFun.call(this.video);
        } else {
          this.isFullScreen = !this.isFullScreen
          const exitFun = document.exitFullscreen || this.document.webkitExitFullScreen;
          exitFun.call(document);
        }
      }
    }
  }
</script>

<style scoped>
  .video {
    position: relative;
  }

  video::-webkit-media-controls {
      display: none !important;
  }

  .video video {
    width: 100%;
    height: 100%;
  }

  .controls {
    width: 100%;
    height: 30px;
    position: absolute;
    bottom: 0;
    left: 0;
    background-color: black;
    opacity: 0.5;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .controls span {
    padding: 0 5px;
    color: #fff;
  }

  .cursor {
    cursor: pointer;
  }
</style>

四、打包组件

 

1.打包环境

由于新版本的vue-cli使用webpack模板创建的vue环境,打包一直出错,所以我们在这里选择使用webpack-simple模板创建的环境作为打包环境。

webpack模板和webpack-simple模板有一些不同,例如配置文件的结构。我们以webpack-simple模板环境为例:

2.components中的index.js

import MyVideo from './MyVideo.vue'

MyVideo.install = function (Vue) {
  if (this.installed) return;
  Vue.component(MyVideo.name, MyVideo)
};

// auto install
if (typeof window !== 'undefined' && window.Vue) {
  MyVideo.install(window.Vue);
}

export default MyVideo

3.修改webpack.config.js配置文件

module.exports = {
  entry: './src/components/index.js',
  externals:{
    vue:'vue'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'MyVideo.js',
    library:'MyVideo',
    libraryTarget:'umd',
    umdNamedDefine: true
  },  
  ...
  ...

entry要修改为我们需要打包的组件同目录下的index.js(该文件编写参考2.节)

externals是排除不需要打包的组件,这里指定vue不打包

output设置输出目录以及输出名称为MyVideo.js

这里注意:

如果打包的组件中使用了一些特殊的文件,例如ttf字体文件等,我们需要安装对应的loader来对其进行处理,在该配置文件中需要添加对应的配置,例如:

{
  test: /\.(woff2?|eot|ttf|otf)$/,
  loader: 'file-loader',
  options: {
    name: '[name].[ext]?[hash]'
  }
}

4.修改package.json配置文件

{
  "name": "myvideoooo",
  "main": "dist/MyVideo.js",
  "description": "Leeoo Video Component",
  "version": "1.0.0",
  "author": "leokale",
  "license": "MIT",
  "private": false,
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --display-error-details --config webpack.config.js"
  },
  "files": [
    "dist"
  ],
  ...
  ...

标黄部分都很重要:

name表示上传包的名称(放在npm仓库中的名称),下载时也是指定这个名字。

main表示上传哪个文件

private设置非私有

猜你喜欢

转载自www.cnblogs.com/leokale-zz/p/12309313.html