随着人们在互联网中停留时间的不断增加,网络视频直播系统发展的越来越好,除了基本的直播功能之外,为了加强观众和主播之间的互动还开发了一些趣味性的娱乐功能,像大转盘等,今天我们就一起来看看在网络视频直播系统开发中,大转盘组件的实现方式吧。
使用案例
/**
* 九宫格游戏参数
* @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;
}
}
}
}
结语
网络视频直播系统中简单的大转盘小游戏就封装好了,这里提供的仅仅是思路噢,肯定还有更好的实现方式,当然大家也可以自行二次开发适应自己的业务,以上就是“网络视频直播系统中大转盘组件的实现”商务全部内容,希望对大家在开发网络视频直播系统时有帮助。