抽奖轮盘
简单来说,就是通过时间控制函数让一个有色蒙版在九宫格上噼里啪啦来回滚动。
你将在这篇文章里分享到我对抽奖功能的理解和代码,学习到简单的实现过程,虽然仅仅是一个demo,但是通过样式的修改,我相信你可以完全应用这个功能。
什么是九宫格抽奖轮盘
关键词:静态(九宫格,有色蒙版)、动态(轮动,速度-四种,步长)
九宫格抽奖轮盘本质是一个带有色彩的蒙版在八个装在九宫格中的div上面的轮动显示;轮动这一功能通过js的时间控制函数实现;蒙版的轮动速度分为匀速、加速、减速、停止四种状态;而如何表达速度呢?我们使用步长这一概念:
- 匀速运动 ,每次轮动时速度和上一次轮动的速度相同,步长相同;
- 加速运动,每次轮动时速度比上一次轮动的速度更快,步长更小;
- 减速运动,每次轮动时速度比上一次轮动的速度更慢,步长更大;
- 停止运动,当前的轮动的速度为0,步长为0;
所以说,我们对抽象速度的操控,本质上是对步长的操控。那么核心代码已经出来了:对“设置步长”、“获取步长”这一对set,get函数的使用就已经涵盖我们要写的所有内容了。而步长就是时间,它会被setTimeout所接收成为参数,进而来控制蒙版的轮动速度。
对于所谓的有色蒙版,html与样式无非是背景颜色的变化。所谓轮动,就是头一个dom的背景颜色消失,同时在后一个dom里出现。但是要用代码实现,只需通过对DOM对象的class类样式的增删即可。
先睹为快
比比再多都不如直接给大家贴代码来的实惠,想直接看代码的可以跳到文章末尾复制code,觉得好的朋友可以点赞支持我。滑动滚轮和点击目录都可实现。
设计程序结构
静态部分
九宫格
由于我做的及其简单,长成这个🐦鸟样。
九宫格主要是一个ul嵌套多个li,让我们来猜猜一共是多少个li呢?九宫格,九宫格,那当然是九个啦!
其实是八个li,通过相对定位把他们摆成这个样子。
蒙版
而蒙版就更简单啦,就是一个类样式,稍稍改变下他的背景。如果动作更复杂的话,可以在后文的js的函数中找到实现途径。
/* 工具样式 */
.red {
background-color: red !important;
}
动态部分
轮动
轮动,直白来说就是轮着动。而这个动的本质是class类名的顺次切换。切换的本体是dom,切换的目标是class。原理就是获取九宫格里的八个dom(手动狗头),先去掉所有的类样式,然后再寻找目标dom去添加类样式。classIndex是我的一个计数器变量。
// 轮动-执行
this.rotationIn = function () {
let li = document.querySelectorAll(".block li");
li.forEach((item) => {
item.classList.remove("red");
});
// 轮动奖盘
li[this.classIndex].classList.add("red");
};
速度
速度有四种,我这里不再赘述。它依赖着步长才能实现。
步长
速度只是一个概念值,他需要 步长 的配合来实现。下面是四种速度的步长实现方法。
// 设置步长 四种态 :uniform-匀速; faster-增速; slowDown-减速; stop-停止;
this.setStep = function (state = "uniform", amount = 0) {
if (state === "uniform") {
this.Step = this.Step;
} else if (state === "faster") {
// 设置默认加速步长
amount = amount === 0 ? 75 : amount;
this.Step = this.Step - amount;
} else if (state === "slowDown") {
// 设置默认减速步长
amount = amount === 0 ? 75 : amount;
this.Step = this.Step + amount;
} else {
console.log(this.Step);
// 设置颓废步长
this.Step = 100000000000;
}
};
其实匀速状态不用操作,加速就减少步长,减速就增加步长,停止就设置步长为超长的时间,之后在执行函数里拦截这个步长值,发现这个值即return false,结束程序即可。
算了不写了,大家直接复制粘贴代码就能用了,写不动了。
上代码
简单实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
/* 全局样式 */
* {
margin: 0;
padding: 0;
list-style: none;
}
body {
padding-left: 100px;
padding-top: 100px;
}
.block {
width: 100%;
height: 100%;
overflow: hidden;
padding-top: 1%;
padding-left: 1%;
background-color: #000;
}
.block li {
position: relative;
float: left;
width: 31%;
height: 31%;
background-color: #fff;
margin-left: 1%;
margin-right: 1%;
margin-top: 1%;
margin-bottom: 1%;
}
/* 更改位置 */
.block li:nth-child(4) {
right: -66%;
}
.block li:nth-child(5) {
right: -33%;
bottom: -33%;
}
.block li:nth-child(6) {
right: 33%;
bottom: -33%;
}
.block li:nth-child(8) {
top: -33%;
left: -33%;
}
/* 工具样式 */
.red {
background-color: red !important;
}
</style>
</head>
<body>
<button onclick="init()">开始</button>
<!-- <button οnclick="turnSwitch()">开关</button> -->
<div style="width: 300px; height: 300px; background: #000">
<ul class="block">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</body>
<script>
function DrawingMachine() {
// 数据列表
this.classIndex = null; // class计数器
this.isTurn = true; // 轮动开关
this.Step = null; // 设置步长
this.created = null;
this.updated = null;
this.finished = null;
this.count = null;
// 构造函数
this.construction = function ({ _index, _step, _c, _u, _f }) {
this.classIndex = _index || 0;
this.Step = _step || 500;
this.count = 0;
this.createdCallback = _c || null;
this.updatedCallback = _u || null;
this.finishedCallback = _f || null;
this.isTurn = true;
};
this.construction({
_index: arguments[0].index,
_step: arguments[0].step,
_c: arguments[0].created,
_u: arguments[0].updated,
_f: arguments[0].finished,
});
// 生命周期事件
this.work_created_callback = function () {
this.createdCallback({ ...this, name: "created" });
// this.$emit()
};
this.work_updated_callback = function () {
this.updatedCallback({
name: "updated",
...this,
step: this.getStep(),
count: this.getCount(),
classIndex: this.classIndex,
isTurn: this.isTurn,
});
// this.$emit()
};
this.work_finished_callback = function () {
this.finishedCallback({
name: "finished",
...this,
step: this.getStep(),
count: this.getCount(),
classIndex: this.classIndex,
isTurn: this.isTurn,
});
// this.$emit()
};
/* 计数器 start */
// 计数器自增
this.increment = function () {
if (this.classIndex < 7) {
this.classIndex++;
} else {
this.classIndex = 0;
}
this.count = this.count + 1;
};
// 获得总轮动次数
this.getCount = function () {
return this.count;
};
/* 计数器部分 start end*/
/* 轮动 start */
// 轮动-关闭或打开
this.turnSwitch = function (flag) {
flag !== undefined ? (this.isTurn = flag) : (this.isTurn = !isTurn);
};
// 轮动-是否允许
this.getSwitch = function () {
if (!this.isTurn || this.Step >= 100000000000) {
return false;
} else {
return true;
}
};
// 轮动-执行
this.rotationIn = function () {
let li = document.querySelectorAll(".block li");
li.forEach((item) => {
item.classList.remove("red");
});
// 轮动奖盘
li[this.classIndex].classList.add("red");
// 自增计数器
this.increment();
};
/* 轮动 start */
/* 步长 start */
// 获取步长
this.getStep = function () {
return this.Step;
};
// 设置步长 四种态 :uniform-匀速; faster-增速; slowDown-减速; stop-停止;
this.setStep = function (state = "uniform", amount = 0) {
if (state === "uniform") {
this.Step = this.Step;
} else if (state === "faster") {
// 设置默认加速步长
amount = amount === 0 ? 75 : amount;
if (this.Step - amount <= 0) {
this.Step = 100000000000;
return false;
}
console.log(this.Step, amount);
this.Step = this.Step - amount;
} else if (state === "slowDown") {
// 设置默认减速步长
amount = amount === 0 ? 75 : amount;
if (this.Step >= 1200) {
this.Step = 100000000000;
return false;
}
this.Step = this.Step + amount;
} else {
console.log(this.Step);
// 设置颓废步长
this.Step = 100000000000;
}
};
/* 步长 end */
/* 核心方法 start */
// 启动
this.doTurn = function () {
this.rotationIn();
this.work_updated_callback();
let steps = this.getStep();
if (!this.getSwitch()) {
// let _f = finished();
console.log("你中奖了", "步长===>", this.Step);
} else {
setTimeout(() => {
this.doTurn();
}, steps);
}
};
/* 核心方法 end */
}
function init() {
let drawingMachine = new DrawingMachine({ step: 680, updated });
drawingMachine.doTurn();
function updated({ step, classIndex, count }) {
console.log("步长速度", step, "当前位置", classIndex, "总轮动数", count);
if (count >= 40) {
drawingMachine.setStep("slowDown", 115);
} else if (step <= 185) {
drawingMachine.setStep("uniform");
} else {
drawingMachine.setStep("faster", 28);
}
}
}
</script>
</html>