移动端基于video标签二次封装样式,记录生活方便以后cv

先给大家看看样式是否符合在考虑要不要copy,因为没有啥技术难度,就是样式,也没有考虑h265等别的兼容性

详情是有全屏按钮的,正常是没有全屏按钮

image.png

image.png

1.在component文件夹下创建一个Myvideo.vue的文件

image.png

2.在component文件夹的index.js中全局引入Myvideo组件

import MyVideo from './MyVideo/index.vue';
Vue.component('MyVideo', MyVideo);

我这里直接上代码了

<template>
    <div class="videoBox" @click.stop="clickVideo">
        <!-- :controls="isPlay ? true : false" -->
        <!-- :poster="cover" 封面图 -->
        <video
            :loop="isDetails ? false : true"
            x5-playsinline
            playsinline="true"
            x-webkit-airplay="allow"
            webkit-playsinline="true"
            x5-video-player-type="h5"
            x5-video-player-fullscreen="true"
            disablePictureInPicture="true"
            :autoplay="isDetails ? true : false"
            controlslist="nodownload noremoteplayback noplaybackrate"
            :src="video"
            ref="video"
            @play="isPlay = true"
            @pause="isPlay = false"
            @timeupdate="timeUpdate"
        ></video>
        <!-- 定位到播放位置 -->
        <div class="position" v-if="targetTime" ref="targetTime">
            上次播放至{{ targetTime }},已续播
        </div>
        <!-- 正在播放 -->
        <div class="pause" ref="pause" v-if="isPlay">
            <div class="time">{{ timeDisplay }}</div>
            <div class="right">
                <svg
                    t="1689131823093"
                    class="icon"
                    viewBox="0 0 1024 1024"
                    version="1.1"
                    xmlns="http://www.w3.org/2000/svg"
                    p-id="7676"
                    width="20"
                    height="20"
                >
                    <path
                        d="M426.666667 138.666667v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334H266.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h106.666666a53.393333 53.393333 0 0 1 53.333334 53.333334z m330.666666-53.333334H650.666667a53.393333 53.393333 0 0 0-53.333334 53.333334v746.666666a53.393333 53.393333 0 0 0 53.333334 53.333334h106.666666a53.393333 53.393333 0 0 0 53.333334-53.333334V138.666667a53.393333 53.393333 0 0 0-53.333334-53.333334z"
                        fill="#ffffff"
                        p-id="7677"
                    ></path>
                </svg>
                <!-- 全屏按钮 -->
                <svg
                    @click.stop="fullscreen"
                    v-if="isDetails"
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke-width="1.5"
                    stroke="currentColor"
                    class="w-70 h-70"
                    color="#fff"
                    style="margin-left: 5rem"
                >
                    <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
                    />
                </svg>
            </div>
        </div>
        <!-- 暂停播放 -->
        <div class="play" ref="play" v-else>
            <div class="time">{{ timeDisplay }}</div>
            <div class="right">
                <svg
                    t="1689131454914"
                    class="icon"
                    viewBox="0 0 1024 1024"
                    version="1.1"
                    xmlns="http://www.w3.org/2000/svg"
                    p-id="6652"
                    width="20"
                    height="20"
                >
                    <path
                        d="M161.2 839.9v-654c0-56.1 60.7-91.1 109.3-63.1l566.3 327c48.6 28 48.6 98.1 0 126.2L270.4 903c-48.5 28-109.2-7.1-109.2-63.1z"
                        fill="#ffffff"
                        p-id="6653"
                    ></path>
                </svg>
                <!-- 全屏按钮 -->
                <svg
                    @click.stop="fullscreen"
                    v-if="isDetails"
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke-width="1.5"
                    stroke="currentColor"
                    class="w-70 h-70"
                    color="#fff"
                    style="margin-left: 5rem"
                >
                    <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
                    />
                </svg>
            </div>
        </div>
        <!-- 时间条 -->
        <div class="timeLine" :class="isPlay ? 'bottom' : 'top'">
            <van-slider
                v-model="sliderVal"
                :min="0"
                :max="sliderMax"
                @change="dragend"
            />
        </div>
        <!-- 重新播放按钮 -->
        <div class="replay" v-if="isReplay" @click="replay">
            <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke-width="1.5"
                stroke="currentColor"
                class="w-100 h-100"
                style="color: #fff"
            >
                <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3"
                />
            </svg>
        </div>
    </div>
</template>
<script>
export default {
    props: {
        cover: {
            typeof: String,
        },
        video: {
            typeof: String,
        },
        // 详情页面的参数
        isDetails: {
            typeof: Boolean,
            default: false,
        },
        time: {
            typeof: String,
        },
    },
    data() {
        return {
            // 是否正在播放
            isPlay: false,
            //总时长
            duration: "00:00",
            // 当前时间
            timeDisplay: "00:00",
            sliderMax: 0,
            sliderVal: 0,
            //播放时间
            targetTime: "",
            //重新播放
            isReplay: false,
        };
    },
    watch: {
        isPlay() {
            this.$nextTick(() => {
                if (this.isPlay) {
                    this.$refs.pause.style.opacity = "1";
                    if (this.targetTime && this.$refs.targetTime) {
                        this.$refs.targetTime.style.opacity = "1";
                    }
                    setTimeout(() => {
                        if (this.$refs.pause) {
                            this.$refs.pause.style.opacity = "0";
                        }
                        if (this.targetTime && this.$refs.targetTime) {
                            this.$refs.targetTime.style.opacity = "0";
                        }
                    }, 1500);
                } else {
                    this.$refs.play.style.opacity = "1";
                    // setTimeout(() => {
                    //     this.$refs.play.style.opacity = "0";
                    // }, 1500);
                }
            });
        },
        time() {
            console.log(this.time, Number(this.time) !== 0);
            if (this.time && Number(this.time) !== 0) {
                console.log(1);
                this.$nextTick(() => {
                    this.$refs.video.currentTime = this.time;
                    this.targetTime = this.formatTime(this.time);
                });
            } else {
                this.targetTime = "";
            }
        },
    },
    mounted() {
        if (this.time && Number(this.time) !== 0) {
            this.$nextTick(() => {
                this.$refs.video.currentTime = this.time;
                this.targetTime = this.formatTime(this.time);
            });
        } else {
            this.targetTime = "";
        }
    },
    methods: {
        // 全屏
        fullscreen() {
            this.$refs.video.pause();
            this.$emit("fullscreen");
            // if (this.$refs.video.requestFullscreen) {
            //     this.$refs.video.requestFullscreen();
            // } else if (this.$refs.video.webkitRequestFullscreen) {
            //     // 兼容性处理
            //     this.$refs.video.webkitRequestFullscreen();
            // }
        },
        // 重新播放
        replay() {
            // 把按钮隐藏
            this.isReplay = false;
            // 将video时间转为0
            this.$refs.video.currentTime = 0;
            // 开始播放
            this.$refs.video.play();
        },
        // 时间条变化
        dragend(val) {
            console.log(val);
            this.$nextTick(() => {
                // 赋值给video的播放时间
                this.$refs.video.currentTime = val;
                this.targetTime = "";
            });
        },
        // 修改时间格式 00:00
        formatTime(seconds) {
            let minutes = Math.floor(seconds / 60);
            let remainingSeconds = seconds % 60;

            let formattedTime = "";
            if (minutes < 10) {
                formattedTime += "0";
            }
            formattedTime += minutes + ":";
            if (remainingSeconds < 10) {
                formattedTime += "0";
            }
            formattedTime += remainingSeconds;

            return formattedTime;
        },
        // 播放时间
        timeUpdate() {
            if (!this.$refs.video) return;
            this.timeDisplay = this.formatTime(
                Math.floor(this.$refs.video.duration) -
                    Math.floor(this.$refs.video.currentTime)
            );
            this.sliderMax = Math.floor(this.$refs.video.duration);
            this.sliderVal = Math.floor(this.$refs.video.currentTime);
            if (this.isDetails) {
                this.$emit("saveTime", this.sliderVal);
                let over = Boolean(
                    Math.floor(this.$refs.video.duration) ===
                        Math.floor(this.$refs.video.currentTime)
                );
                if (over) {
                    this.isReplay = true;
                } else {
                    this.isReplay = false;
                }
            }
        },
        clickVideo() {
            if (this.isPlay) this.$refs.video.pause();
            else this.$refs.video.play();
        },
    },
};
</script>
<style lang="scss" scoped>
:deep .van-slider__bar {
    transition: all 1s;
}
.videoBox {
    position: relative;
    min-height: 200rem;
    max-height: 390rem;
    video {
        width: 100%;
        min-height: 200rem;
        max-height: 390rem;
        object-fit: cover;
        object-position: center;
    }
    .position {
        position: absolute;
        bottom: 28rem;
        left: -8rem;
        font-size: 12rem;
        color: white;
        padding: 5rem 15rem;
        background: rgba(34, 34, 34, 0.237) 0;
        transform: scale(0.85);
        transition: 0.5s;
    }
    .play {
        z-index: 2;
        position: absolute;
        // bottom: 15rem;
        // left: 15rem;
        // top: 50%;
        // left: 50%;
        // transform: translate(-50%, -50%);
        bottom: 0;
        opacity: 1;
        width: 100%;
        height: 40rem;
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0 10rem 0 15rem;
        transition: 0.8s;
        background: linear-gradient(
            to bottom,
            transparent,
            rgba(0, 0, 0, 0.273)
        );
        .time {
            color: white;
            font-size: 15rem;
            padding-top: 4rem;
        }
        .right {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
    }
    .pause {
        @extend .play;
    }

    .timeLine {
        position: absolute;
        z-index: 3;
        width: 100%;
    }
    .bottom {
        bottom: 0;
        .van-slider {
            height: 3rem;
        }
        :deep .van-slider__button {
            display: none !important;
        }
        :deep .van-slider__bar {
            background-color: #001fffe8;
        }
    }
    .top {
        bottom: 15rem;
        width: 60%;
        left: 21%;
        .van-slider {
            height: 5rem;
            background-color: #ffffffa5;
        }
        :deep .van-slider__button {
            width: 12rem;
            height: 12rem;
        }
        :deep .van-slider__bar {
            background-color: #001fffe8;
        }
    }
    .replay {
        position: absolute;
        width: 50rem;
        height: 50rem;
        border-radius: 50%;
        background-color: #0000007a;
        display: flex;
        justify-content: center;
        align-items: center;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        z-index: 3;
    }
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值