网络视频直播系统中大转盘组件的实现

随着人们在互联网中停留时间的不断增加,网络视频直播系统发展的越来越好,除了基本的直播功能之外,为了加强观众和主播之间的互动还开发了一些趣味性的娱乐功能,像大转盘等,今天我们就一起来看看在网络视频直播系统开发中,大转盘组件的实现方式吧。

使用案例

/**
 * 九宫格游戏参数
 * @param {Object} pics - 礼品图片对象集合,自行使用import导入进来
 *      @example {gift1:  () => import('')}
 * @param {Object} options - 大转盘配置项
 * @param {Object} giftName - 礼品名称对应的上面pics中图片的名称,因为图片上只有礼品的英文名称相信,所以这里弄了个英文名称相信对应的礼品名称信息
 *      @example {gift1: "Yoyo抱枕"} 做了一层图片文件名与礼品名称之间的映射,方便$message弹出信息
 * @param {number} targetIndex - 中奖的位置
 * @param {Object} positionIndex - 转动顺序规则的映射,默认顺时针,详情可看组件代码配置注释
 * @param {func} clickLottery - 点击抽奖按钮的回调
 * @param {func} complete - 大转盘运行结束的回调
 * @returns {}
 */
<LuckGame 
    :pics="pics"
    :options="options" 
    :giftName="giftName" 
    :targetIndex="targetIndex" 
    @clickLottery="fetchGiftInfo" 
    @complete="showGift"
    >
</LuckGame>

关于组件源码

单文件组件.vue
先讲下大致的实现思路:声明一个定时器,在网络视频直播系统运行过程中一直存在,当加速、匀速、减速时仅仅改变的是这个定时器的时间(在这里也就是速度this.optionData.speed,这个值越小,触发定时器的频率越快,速度越快;这个定时器实现其实就是反复切换激活元素的位置,达到大转盘“滚动”的效果),其它的一切操作都是围绕这个来的。

<!-- 九宫格 -->
<template>
    <div class="clearfix flex luck-game">
        <div :class="[`luck-unit luck-unit-${i - 1}`]" v-for="i of 9" :key="i" ref="gifts">
            <template v-if="i === 5">
                <div @click="lottery" class="lottery">
                    <slot name="btn">
                        <p class="num">200钻石/</p>
                        <p class="tit">抽奖</p>
                        <div class="img"></div>
                    </slot>
                </div>
            </template>
        </div>
    </div>
</template><script>
export default {
    data() {
        return {
            optionData: this.options
        };
    },
​
    props: {
        pics: {
            type: Object,
            require: true
        },
        options: {
            type: Object,
            require: true
        },
        targetIndex: {
            type: [Number, null]
        },
        giftName: {
            type: Object
        },
        /*
        dom顺序            转动顺序
            0, 1, 2            0, 1, 2
            3, 4, 5            8, 4, 3
            6, 7, 8            7, 6, 5
        */
        // 默认顺时针转动规则
        positionIndex: {
            type: Object,
            default() {
                return {
                    3: 5,
                    5: 8,
                    6: 7,
                    7: 6,
                    8: 3
                };
            }
        }
    },
    computed: {
        count() {
            return this.$refs.gifts.length;
        },
        gifts() {
            return this.$refs.gifts;
        },
        index() {
            return this.optionData.index % this.count;
        }
    },mounted() {
        this.optionData.speed = this.optionData.initSpeed;
        this.initGiftPic();
        this.setActiveDom(this.getIndex(this.optionData.index));
    },
​
    methods: {
        lottery() {
            if (this.optionData.isRunning) {
                this.$message.warning("正在拼命给您领取礼物,请稍后😀");
                return;
            }
            this.$emit("clickLottery");
            this.roll();
        },
        roll() {
            let activeDom = this.getActiveDom();
            activeDom.classList.remove("active");
            ++this.optionData.index;
            // 跳过中间的按钮
            if (this.index === 4) {
                ++this.optionData.index;
            }
            // 对于运行的顺序可以自定义关联规则去修改
            activeDom = 
                this.gifts.find((gift) => gift.classList.contains(`luckunit-${this.getIndex(this.index)}`));
            activeDom.classList.add("active");
​
            this.timer = setTimeout(() => {
                this.roll();
            }, this.optionData.speed);  // 速度值越小,触发定时器的时间越短,故速度越快,控制speed的值即可控制转动的速度
            
            if (!this.optionData.isRunning) {
                let timing = this.getRandomTime(this.optionData.upTimer);
                this.speedUp(timing);
                this.optionData.isRunning = true;
            }
        },
        speedUp(timing) {
            let upTimer;if (this.optionData.speed >= this.optionData.upMax) {
                upTimer = setTimeout(() => {
                    this.optionData.speed -= this.optionData.upStep;
                    this.speedUp(timing);
                }, timing);
            } else {
                this.speedConstant();
                clearTimeout(upTimer);
            }
        },
        speedConstant() {
            let constantTimer = setTimeout(() => {
                let timing = this.getRandomTime(this.optionData.downTimer);
                this.speedDown(timing);
                clearTimeout(constantTimer);
            }, this.optionData.constantTiming);
        },
        speedDown(timing) {
            let downTimer;
            if (this.optionData.speed >= this.optionData.downMax && this.targetIndex === this.index) {
                this.stop();
                clearTimeout(downTimer);
            } else {
                downTimer = setTimeout(() => {
                    this.optionData.speed += this.optionData.downStep;
                    this.speedDown(timing);
                }, timing);
            }
        },
        stop() {
            this.$message.success(`恭喜您取得${this.getActiveDom().title}`);
            clearTimeout(this.timer);
            this.$emit("complete", this.getActiveDom());
            this.optionData.isRunning = false;
        },
        getRandomTime(timing) {
            return (Math.random() * 4 + 0.4) * timing;
        },
        initGiftPic() {
            this.gifts.forEach((giftBox) => {
                // 设定随机礼物
                const random = Math.ceil(Math.random() * Object.keys(this.pics).length);
                // 排除抽奖按钮
                if (giftBox.children.length === 0) {
                    let giftIndex = `gift${random}`;
                    let url = this.pics[giftIndex];
                    giftBox.style.backgroundImage = `url('${url}')`;
                    giftBox.title = this.giftName[giftIndex];
                }
            });
        },
        getActiveDom() {
            return this.gifts.find((gift) => gift.classList.contains("active"));
        },
        setActiveDom(index) {
            this.gifts[index] && this.gifts[index].classList.add("active");
        },
        getIndex(index) {
            return this.positionIndex[index] || index;
        }
    }
};
</script>
<style lang="less" scoped>
@import url("./index.less");
</style>

less样式文件
网络视频直播系统这里唯一引入的图片文件就是中间btn的,可以自行引入

.luck-game {
    width: 486px;
    height: 478px;
    margin: auto;
    background: skyblue;
    flex-wrap: wrap;
    .luck-unit {
        float: left;
        flex-basis: 33.33%;
        height: 33.33%;
        border-radius: 16px;
        background-size: 50%;
        background-repeat: no-repeat;
        background-position: center;
        animation: all 0.3s;
        &.active {
            background-color: rgba(255, 204, 149, 0.5);
            &.luck-unit {
                background-size: 58%;
            }
        }
        &.luck-unit-4 {
            background-image: url("~@src/img/common/juejin.svg");
            background-size: contain;
            background-position: center center;
            background-repeat: no-repeat;
            background-size: 92%;
            color: #3e0b08;
            font-weight: 700;
            position: relative;
            cursor: pointer;
            display: flex;
            flex-direction: column;
            justify-content: center;
            .lottery {
                display: flex;
                flex-direction: column;
                justify-content: center;
            }
            .num,
            .tit {
                z-index: 3;
                text-align: center;
                // color: #fff;
            }
            .tit {
                text-shadow: 1px 1px 10px 0px rgba(49, 27, 17, 0.72);
                font-size: 37px;
            }
            .img {
                position: absolute;
                z-index: 2;
                background-image: url("~@src/img/common/juejin.svg");
                background-size: contain;
                background-position: center center;
                background-repeat: no-repeat;
                // top\与 background-position-y互为相反数
                top: 0px;
                background-position-y: -0px;
                height: 100%;
                width: 100%;
                transition: all 0.3s;
            }
            &:hover .img {
                background-image: url("~@src/img/common/juejin.svg");
                background-size: contain;
                background-position: center center;
                background-repeat: no-repeat;
            }
        }
    }
}

结语
网络视频直播系统中简单的大转盘小游戏就封装好了,这里提供的仅仅是思路噢,肯定还有更好的实现方式,当然大家也可以自行二次开发适应自己的业务,以上就是“网络视频直播系统中大转盘组件的实现”商务全部内容,希望对大家在开发网络视频直播系统时有帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值