zoukankan      html  css  js  c++  java
  • [前端] Vue封装播放器、打包、上传NPM

    一、使用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 {
         100%;
        height: 100%;
      }
      .controls {
         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 {
         100%;
        height: 100%;
      }
    
      .controls {
         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": "leeoovideo123",
      "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仓库中的名称),下载时也是指定这个名字。注意,名字中不能有大写,例如leeooPlayer就不行。

    main表示上传哪个文件

    private设置非私有

    files表示要打包的目录,这里我们只打包了dist目录,如果该组件使用到了其他的文件,例如字体文件在assets目录中,css文件在src/styles目录中,则都需要打包进去:

    "files": [
        "dist",
        "assets",
        "src/styles"
    ],

    如果文件没打包齐全,可能组件的样式,字体,图标等无法正确显示。

    5.编写README

    对于组件的安装和使用方法,可以写到README文件中。

    README的内容会显示在npm网站中。

    6.打包

    配置文件修改完毕后,使用命令进行打包:

    npm run build

    会在dist目录中生成js文件:

    至此,组件打包完毕。

    五、上传到npm仓库

    1.注册npm

    npm网站:https://www.npmjs.com/

    1)注册个人账号

    2)认证邮箱(一定要去邮箱里点击链接认证)

    2.上传组件

    1)运行命令登录:

    npm login

    按提示输入npm的账号密码和邮箱。

    2)在项目目录下运行命令

    npm publish

    上传成功后,可以在npm网站的个人packages中查看到上传成功的包。

    如果上传的组件名(package.json中配置的name)与仓库中已存在的包名字相同或很像,则会提示报错,需要重新修改名称再上传。

    3)删除包

    npm unpublish

    注意,删除包后,如果再上传同名字的包会有24小时的限制。

    3.更新组件版本

    只需要保证上传组件的名称一致,然后修改package.json的版本,重新打包上传即可。

    六、下载和使用包

    1.npm安装

    npm i leeoovideo123 -S

    2.cnpm安装

    cnpm每10分钟从npm同步数据,所以10分钟后cnpm就可以安装我们上传的包了

    cnpm i leeoovideo123 -S

    3.检查包是否安装

    在node_modules目录下可以找到我们安装的包:

    在检查package.json:

    "dependencies": {
      "leeoovideo123": "^1.0.0",
      "vue": "^2.5.2",
      "vue-router": "^3.0.1"
    },

    如果没有对应的配置,可以手工添加。

    4.导入和使用包

    在main.js中:

    import MyVideo from 'leeoovideo123'
    import 'leeoovideo123/src/styles/style.css'
    Vue.use(MyVideo)

    这里注意,虽然我们上传到npm的包名是"leeoovideo123",但是组件的名称实际上是"MyVideo"。

    所以,我们在使用的时候一定要导入"MyVideo"。

    尽量在打包时保证组件名与包名一致,以免使用不便(可以在ReadMe中说明)。

    在我们的组件App中使用:

    // App.vue
    
    <template>
      <div id="app">
        <MyVideo src="https://video.pearvideo.com/mp4/third/20200212/cont-1651180-11487675-112807-hd.mp4"></MyVideo>
      </div>
    </template>

    页面效果:

     (✿◠‿◠)

  • 相关阅读:
    Verilog语言
    OrCAD --从SNAPEDA导入封装库
    RAM/ROM IP一次性总结
    USB之Main item, Local item和Global item 的作用范围与归类
    发光LED压降与工作电流总结
    C之输入输出函数(3) -- 请使用sscanf()
    C之输入输出函数(2) -- gets()
    C之输入输出函数(1) -- fgets()
    C中的lvalue和rvalue
    关于字符串的一点补充
  • 原文地址:https://www.cnblogs.com/leokale-zz/p/12309313.html
Copyright © 2011-2022 走看看