|
@@ -0,0 +1,142 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="c-live iconfont"
|
|
|
|
|
+ :style="styles"
|
|
|
|
|
+ >
|
|
|
|
|
+ <video
|
|
|
|
|
+ ref="player"
|
|
|
|
|
+ class="c-live__inst"
|
|
|
|
|
+ :muted.prop="muted"
|
|
|
|
|
+ />
|
|
|
|
|
+ <canvas
|
|
|
|
|
+ v-show="isSnapping"
|
|
|
|
|
+ ref="canvas"
|
|
|
|
|
+ class="c-live__canvas"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+import HlsJs from 'hls.js'
|
|
|
|
|
+
|
|
|
|
|
+const isSupported = HlsJs.isSupported()
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'CLive',
|
|
|
|
|
+ inject: ['control'],
|
|
|
|
|
+ props: {
|
|
|
|
|
+ node: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ default: null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ isSnapping () {
|
|
|
|
|
+ return this.control.snapping
|
|
|
|
|
+ },
|
|
|
|
|
+ styles () {
|
|
|
|
|
+ const {
|
|
|
|
|
+ width,
|
|
|
|
|
+ height,
|
|
|
|
|
+ radius
|
|
|
|
|
+ } = this.node
|
|
|
|
|
+ return {
|
|
|
|
|
+ width: `${width}px`,
|
|
|
|
|
+ height: `${height}px`,
|
|
|
|
|
+ 'font-size': `${Math.min(width, height) / 2 | 0}px`,
|
|
|
|
|
+ 'border-radius': `${radius}px`
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ url () {
|
|
|
|
|
+ return this.node.url
|
|
|
|
|
+ },
|
|
|
|
|
+ muted () {
|
|
|
|
|
+ return this.node.mute || this.control.muted
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ url (val) {
|
|
|
|
|
+ console.log('watch', val)
|
|
|
|
|
+ this.play()
|
|
|
|
|
+ },
|
|
|
|
|
+ isSnapping (val) {
|
|
|
|
|
+ const player = this.$refs.player
|
|
|
|
|
+ if (player) {
|
|
|
|
|
+ if (val) {
|
|
|
|
|
+ this.getSnap()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const canvas = this.$refs.canvas
|
|
|
|
|
+ if (canvas) {
|
|
|
|
|
+ canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ mounted () {
|
|
|
|
|
+ this.url && this.play()
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeDestroy () {
|
|
|
|
|
+ if (this.hlsjs) {
|
|
|
|
|
+ this.hlsjs.destroy()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ play () {
|
|
|
|
|
+ if (isSupported) {
|
|
|
|
|
+ if (!this.hlsjs) {
|
|
|
|
|
+ this.hlsjs = new HlsJs()
|
|
|
|
|
+ this.hlsjs.attachMedia(this.$refs.player)
|
|
|
|
|
+ this.hlsjs.on(HlsJs.Events.MANIFEST_PARSED, () => {
|
|
|
|
|
+ this.$refs.player.play()
|
|
|
|
|
+ })
|
|
|
|
|
+ this.hlsjs.on(HlsJs.Events.ERROR, e => {
|
|
|
|
|
+ console.log('error', e)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ this.hlsjs.loadSource(this.url)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ getSnap () {
|
|
|
|
|
+ const video = this.$refs.player
|
|
|
|
|
+ const canvas = this.$refs.canvas
|
|
|
|
|
+ if (video && canvas) {
|
|
|
|
|
+ const cxt = canvas.getContext('2d')
|
|
|
|
|
+ canvas.width = this.node.width
|
|
|
|
|
+ canvas.height = this.node.height
|
|
|
|
|
+ cxt.drawImage(video, 0, 0, this.node.width, this.node.height)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.c-live {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ background-color: rgba(255, 255, 255, .8);
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+
|
|
|
|
|
+ &::before {
|
|
|
|
|
+ content: '\e772';
|
|
|
|
|
+ font-family: element-icons;
|
|
|
|
|
+ font-size: inherit;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &__inst,
|
|
|
|
|
+ &__canvas {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &__inst {
|
|
|
|
|
+ object-fit: fill;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|