vue 结合 videojs 实现视频播放组件
简介
业务需求,视频播放组件往往结合视频上传组件一块使用。
主要依赖说明 (先安装,步骤略)
1 | { |
2 | "element-ui": "2.11.1", |
3 | "vue": "^2.6.10", |
4 | "vue-router": "^3.0.1", |
5 | "vue-video-player": "^5.0.2" |
6 | } |
正文
1.组件
src/components/VideoPlayer/index.vue
1 | <template> |
2 | <div :id="videoId" class="video-js-player-container" allowfullscreen> |
3 | <video-player |
4 | playsinline |
5 | oncontextmenu="return false;" |
6 | :options="playerOptions" |
7 | class="vjs-big-play-centered" |
8 | @canplay="canplay" |
9 | /> |
10 | </div> |
11 | </template> |
12 | |
13 | <script> |
14 | import videojs from "video.js"; |
15 | |
16 | import { videoPlayer } from "vue-video-player"; |
17 | window.videojs = videojs; |
18 | const zhCN = require("video.js/dist/lang/zh-CN.js"); |
19 | export default { |
20 | name: "VideoPlayer", |
21 | components: { |
22 | videoPlayer |
23 | }, |
24 | props: { |
25 | // 视频地址 |
26 | src: { |
27 | required: true, |
28 | default: "" |
29 | }, |
30 | // 是否自动播放 |
31 | autoplay: { |
32 | type: Boolean, |
33 | default: false |
34 | }, |
35 | loop: { |
36 | type: Boolean, |
37 | default: true |
38 | }, |
39 | // 视频海报 |
40 | poster: { |
41 | type: String, |
42 | default: "" |
43 | }, |
44 | // 视频高度 |
45 | height: { |
46 | type: Number, |
47 | default: 9 * 50 |
48 | }, |
49 | // 视频宽度 |
50 | width: { |
51 | type: Number, |
52 | default: 16 * 50 |
53 | } |
54 | }, |
55 | data() { |
56 | return { |
57 | video: "", |
58 | videoId: "videojs-" + +new Date(), |
59 | playerOptions: { |
60 | languages: zhCN, |
61 | preload: "auto", |
62 | fluid: true, |
63 | sources: [ |
64 | { |
65 | src: "" |
66 | } |
67 | ], |
68 | loop: this.loop, |
69 | autoplay: this.autoplay, |
70 | poster: this.poster, |
71 | height: this.height, |
72 | width: this.width |
73 | } |
74 | }; |
75 | }, |
76 | watch: { |
77 | src(val) { |
78 | if (val) { |
79 | this.playerOptions.sources[0].src = val; |
80 | } |
81 | } |
82 | }, |
83 | mounted() { |
84 | // 分发时长 |
85 | this.video = document.querySelector(`#${this.videoId} .vjs-tech`); |
86 | this.video.oncanplay = e => { |
87 | this.$emit("subVideoDuration", e.target.duration); |
88 | }; |
89 | }, |
90 | |
91 | methods: { |
92 | canplay(e) { |
93 | const duration = e.el_.children[0].duration; |
94 | console.log(duration); |
95 | this.$emit("subVideoDuration", duration); |
96 | } |
97 | } |
98 | }; |
99 | </script> |
100 | <style lang="scss"> |
101 | .video-js-player-container { |
102 | border: 1px solid #ccc; |
103 | .video-js .vjs-big-play-button { |
104 | font-size: 2.5em; |
105 | line-height: 2.3em; |
106 | height: 2.5em; |
107 | width: 2.5em; |
108 | -webkit-border-radius: 2.5em; |
109 | -moz-border-radius: 2.5em; |
110 | border-radius: 2.5em; |
111 | background-color: #73859f; |
112 | background-color: rgba(115, 133, 159, 0.5); |
113 | border-width: 0.15em; |
114 | margin-top: -1.25em; |
115 | margin-left: -1.75em; |
116 | } |
117 | /* 中间的播放箭头 */ |
118 | .vjs-big-play-button .vjs-icon-placeholder { |
119 | font-size: 1.63em; |
120 | } |
121 | /* 加载圆圈 */ |
122 | .vjs-loading-spinner { |
123 | font-size: 2.5em; |
124 | width: 2em; |
125 | height: 2em; |
126 | border-radius: 1em; |
127 | margin-top: -1em; |
128 | margin-left: -1.5em; |
129 | } |
130 | .video-js.vjs-playing .vjs-tech { |
131 | pointer-events: auto; |
132 | } |
133 | .video-js .vjs-time-control { |
134 | display: block; |
135 | } |
136 | .video-js .vjs-remaining-time { |
137 | display: none; |
138 | } |
139 | .vjs-button > .vjs-icon-placeholder:before { |
140 | font-size: 1.8em; |
141 | line-height: 2.12; |
142 | } |
143 | .vjs-paused .vjs-big-play-button, |
144 | .vjs-paused.vjs-has-started .vjs-big-play-button { |
145 | display: block; |
146 | } |
147 | // 禁止右键 |
148 | video::-webkit-media-controls-enclosure { |
149 | overflow: hidden; |
150 | } |
151 | video::-webkit-media-controls-panel { |
152 | width: calc(100% + 30px); |
153 | } |
154 | .vjs-poster { |
155 | background-size: cover; |
156 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
157 | } |
158 | .video-js .vjs-play-progress { |
159 | background-color: #d2bbad; |
160 | } |
161 | } |
162 | </style> |
2.使用
1 | <template> |
2 | <div> |
3 | <video-player |
4 | :src="url" |
5 | @subVideoDuration="subVideoDuration" |
6 | ></video-player> |
7 | </div> |
8 | </template> |
9 | |
10 | <script> |
11 | import VideoPlayer from "@/components/VideoPlayer"; |
12 | export default { |
13 | name: "GoodsForm", |
14 | components: { |
15 | VideoPlayer |
16 | }, |
17 | data() { |
18 | return { |
19 | url: |
20 | "http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" |
21 | }; |
22 | }, |
23 | methods: { |
24 | // 视频时长 |
25 | subVideoDuration(duration) { |
26 | console.log(duration); |
27 | } |
28 | } |
29 | }; |
30 | </script> |
3.使用效果