<template> <div class="video-player vjs-custom-skin"> <video class="video-js"></video> </div> </template> <script> // ref import videojs from 'video.js' import 'video.js/dist/video-js.css' export default { name: 'video-player', props: { options: { type: Object, required: true }, start: { type: Number, default: 0 }, playsinline: { type: Boolean, default: false }, customEventName: { type: String, default: 'statechanged' } }, mounted() { if (!this.player) { this.initialize() } }, beforeDestroy() { if (this.player) { this.dispose() } }, methods: { initialize() { // init var self = this this.player = null // videojs options var videoOptions = Object.assign({ autoplay: false, controls: true, preload: 'auto', fluid: false, muted: false, width: '100%', height: '360', language: 'en', controlBar: { remainingTimeDisplay: false, playToggle: {}, progressControl: {}, fullscreenToggle: {}, volumeMenuButton: { inline: false, vertical: true } }, techOrder: ['html5'], plugins: {} }, this.options) // check sources /* if (!videoOptions.sources || !videoOptions.sources.length) { console.warn('Missing required option: "sources".') return false } */ // ios fullscreen var playsinline = this.playsinline if (playsinline) { this.$el.children[0].setAttribute('playsinline', playsinline) this.$el.children[0].setAttribute('webkit-playsinline', playsinline) } // emit event var emitPlayerState = function(event, value) { if (event) { self.$emit(event, self.player) } if (value) { var values = {} values[event] = value self.$emit(self.customEventName, values) } } // videoOptions // console.log(videoOptions) // avoid error "VIDEOJS: ERROR: Unable to find plugin: __ob__" if (videoOptions.plugins) { delete videoOptions.plugins.__ob__ } this.player = videojs(this.$el.children[0], videoOptions, function() { // player readied var _this = this self.$emit('ready', self.player) // events var events = ['loadeddata', 'canplay', 'canplaythrough', 'play', 'pause', 'waiting', 'playing', 'ended', 'error' ] for (var i = 0; i < events.length; i++) { (function(event) { _this.on(event, function() { emitPlayerState(event, true) }) })(events[i]) } this.on('timeupdate', function() { emitPlayerState('timeupdate', this.currentTime()) }) }) }, dispose() { if (this.player && videojs) { if (this.player.techName_ !== 'Flash') { this.player.pause && this.player.pause() } videojs(this.$el.children[0]).dispose() if (!this.$el.children.length) { var video = document.createElement('video') video.className = 'video-js' this.$el.appendChild(video) } this.player = null } } }, watch: { options: { deep: true, handler: function(options, oldOptions) { this.dispose() if (options && options.sources && options.sources.length) { this.initialize() } } } } } </script> <style lang="less"> .vjs-custom-skin > .video-js { width: 100%; font-family: "PingFang SC","Helvetica Neue","Hiragino Sans GB","Segoe UI","Microsoft YaHei","微软雅黑",sans-serif; } .video-js.vjs-no-flex .vjs-menu-button-inline, .vjs-custom-skin > .video-js .vjs-menu-button-inline.vjs-slider-active, .vjs-custom-skin > .video-js .vjs-menu-button-inline:focus, .vjs-custom-skin > .video-js .vjs-menu-button-inline:hover { width: 10em; } .vjs-custom-skin > .video-js .vjs-controls-disabled .vjs-big-play-button { display: none!important; } .vjs-custom-skin > .video-js .vjs-control { width: 3em; } .vjs-custom-skin > .video-js .vjs-control.vjs-live-control { width: auto; padding-left: 0.5em; letter-spacing: 0.1em; } .vjs-custom-skin > .video-js .vjs-menu-button-inline:before { width: 1.5em; } .vjs-menu-button-inline .vjs-menu { left: 3em; } .video-js.vjs-ended .vjs-big-play-button, .video-js.vjs-paused .vjs-big-play-button, .vjs-paused.vjs-has-started.vjs-custom-skin > .video-js .vjs-big-play-button { display: block; } .vjs-custom-skin > .video-js .vjs-load-progress div, .vjs-seeking .vjs-big-play-button, .vjs-waiting .vjs-big-play-button { display: none!important; } .vjs-custom-skin > .video-js .vjs-mouse-display:after, .vjs-custom-skin > .video-js .vjs-play-progress:after { padding: 0 0.4em 0.3em; } .video-js.vjs-ended .vjs-loading-spinner { display: none; } .video-js.vjs-ended .vjs-big-play-button { display: block !important; } .video-js.vjs-ended .vjs-big-play-button, .video-js.vjs-paused .vjs-big-play-button, .vjs-paused.vjs-has-started.vjs-custom-skin > .video-js .vjs-big-play-button { display: block; } .vjs-custom-skin > .video-js .vjs-big-play-button { top: 50%; left: 50%; margin-left: -1.5em; margin-top: -1em; } .vjs-custom-skin > .video-js .vjs-big-play-button { background-color: rgba(0,0,0,0.45); font-size: 3.5em; border-radius: 50%; height: 3em !important; line-height: 3em !important; margin-top: -1.5em !important; } .video-js:hover .vjs-big-play-button, .vjs-custom-skin > .video-js .vjs-big-play-button:active, .vjs-custom-skin > .video-js .vjs-big-play-button:focus { background-color: rgba(36,131,213,0.9); } .vjs-custom-skin > .video-js .vjs-loading-spinner { border-color: rgba(36,131,213,0.8); } .vjs-custom-skin > .video-js .vjs-control-bar2 { background-color: #000000; } .vjs-custom-skin > .video-js .vjs-control-bar { /*background-color: rgba(0,0,0,0.3) !important;*/ color: #ffffff; font-size: 14px; } .vjs-custom-skin > .video-js .vjs-play-progress, .vjs-custom-skin > .video-js .vjs-volume-level { background-color: #2483d5; } .vjs-custom-skin > .video-js .vjs-play-progress:before { top: -0.3em; } .vjs-custom-skin > .video-js .vjs-progress-control:hover .vjs-progress-holder { font-size: 1.3em; } .vjs-menu-button-popup.vjs-volume-menu-button-vertical .vjs-menu { left: 0; } .vjs-custom-skin > .video-js .vjs-menu li { padding: 0; line-height: 2em; font-size: 1.1em; font-family: "PingFang SC","Helvetica Neue","Hiragino Sans GB","Segoe UI","Microsoft YaHei","微软雅黑",sans-serif; } .vjs-custom-skin > .video-js .vjs-mouse-display:after, .vjs-custom-skin > .video-js .vjs-play-progress:after, .vjs-custom-skin > .video-js .vjs-time-tooltip { border-radius: 0; font-size: 1em; padding: 0; width: 3em; height: 1.5em; line-height: 1.5em; top: -3em; } .vjs-custom-skin > .video-js .vjs-menu-button-popup .vjs-menu { width: 5em; left: -1em; } .vjs-custom-skin > .video-js .vjs-menu-button-popup.vjs-volume-menu-button-vertical .vjs-menu { left: 0; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-resolution-button .vjs-menu { /*order: 4;*/ } /*排序顺序*/ .vjs-custom-skin > .video-js .vjs-control-bar .vjs-play-control { order: 0; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-time-control { min-width: 1em; padding: 0; margin: 0 0.1em; text-align: center; display: block; order: 1; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-playback-rate .vjs-playback-rate-value { font-size: 1.2em; line-height: 2.4; } .vjs-custom-skin > .video-js .vjs-progress-control.vjs-control { order: 2; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-volume-menu-button { order: 3; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-resolution-button { order: 4; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-resolution-button .vjs-resolution-button-label { display: block; line-height: 3em; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-playback-rate { order: 5; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-fullscreen-control { order: 6; } </style>