快应用-大转盘抽奖活动
一、小米厂商
<template>
<stack id="stack">
<div class="wrapper">
<div class="page-content-box">
<div class="lucky-box">
<div class="content-box" id="animation">
<div
for="list"
class="prize-row"
style="transform:rotate({{$item.turn}}deg)"
>
<text>{{ $item.label }}</text>
</div>
</div>
<img
class="go-btn"
@click="onCallAnimationClick"
src="../../assets/images/go.png"
alt=""
/>
</div>
<text class="reset-btn" @click="resetTurntableHandle">重置转盘</text>
</div>
</div>
</stack>
</template>
<script>
let $animation = null
export default {
public: {},
// 页面级组件的数据模型,影响传入数据的覆盖机制:private内定义的属性不允许被覆盖
private: {
list: [
{
label: "1",
value: "0",
turn: 0
},
{
label: "2",
value: "1",
turn: 60
},
{
label: "3",
value: "2",
turn: 120
},
{
label: "4",
value: "3",
turn: 180
},
{
label: "5",
value: "4",
turn: 240
},
{
label: "6",
value: "5",
turn: 300
}
],
// 动画时间
animationDuration: 1500,
// 动画是否正在运动
mTextState: 'Init',
},
async onInit() { },
// 转盘动画执行
onCallAnimationClick() {
if (!['finished', 'Init'].includes(this.mTextState)) {
return
}
let keyframes = [
{
transform: {
rotate: "0deg"
},
time: 0
}
]
let index = $utils.getRandomNumber(0, 5)
// 旋转圈数
let rotateTrunNum = 2
// 扇形区域等分数量
let dengfen = 6
// for循环长度(固定旋转圈数(计算旋转区域数) + 最后停留偏移量(偏移扇形数)
// 这里偏移量计算:由于转盘有设置固定旋转2圈,那么动画停止的时候时发生在转盘转第三圈,
// 但是第三圈停留的扇形区域度数 和奖品列表排序是恰好相反的,所以这里需要用区域等分数减去中奖索引
let len = rotateTrunNum * dengfen + (dengfen - index)
// 下方的time取值范围在 0 - 100,为每一个关键帧动画执行进度,所以这里需要由关键帧动画数组集合中的所有
// 数据均分100;并需要注意:起始和结束数据分别固定为0和100
for (let i = 1; i <= len; i++) {
keyframes.push({
transform: {
rotate: 60 * i + "deg"
},
time: (100 / len) * i
})
}
// console.log("关键帧动画组:", keyframes);
const options = {
duration: this.animationDuration,
easing: 'linear',
delay: 0,
fill: 'forwards',
iterations: 1
}
const cAnimationNode = this.$element('animation')
$animation = cAnimationNode.animate(keyframes, options)
$animation.play()
this.mTextState = $animation.playState
// 动画执行结束
// 这里的实例事件本地调用无法触发,需要真机调试查看
$animation.onfinish = () => {
console.log('动画结束--实例事件调用');
this.mTextState = $animation.playState
// ... 转盘动画结束后业务逻辑
}
},
// 重置转盘
resetTurntableHandle() {
if ($animation) {
this.mTextState = "Init"
const finishedA = [
{
transform: {
rotate: "0deg"
},
time: 0
},
{
transform: {
rotate: "0deg"
},
time: 100
}
]
let options = {
duration: 50,
easing: 'linear',
delay: 0,
fill: 'none',
iterations: 1
}
const cAnimationNode = this.$element('animation')
$animation = cAnimationNode.animate(finishedA, options)
$animation.play()
}
},
}
</script>
<style lang="less">
@import './../../assets/styles/style.less';
.wrapper {
width: 750px;
.flex-box-mixins(column, flex-start, center);
background-color: #f0ca9e;
padding-bottom: 111px;
}
.page-content-box {
width: 100%;
height: 100%;
padding-top: 120px;
background-color: #f0ca9e;
.flex-box-mixins(column, flex-start, center);
}
.lucky-box {
margin-top: 62px;
width: 668px;
height: 668px;
background-image: url('../../assets/images/lucky-bg.png');
background-repeat: no-repeat;
background-size: 100%;
position: relative;
justify-content: center;
align-items: center;
.content-box {
width: 558px;
height: 558px;
flex-direction: column;
background-image: url('../../assets/images/lucky-face.png');
background-repeat: no-repeat;
background-size: 100%;
position: relative;
border-radius: 50%;
overflow: hidden;
.prize-row {
width: 558px;
position: absolute;
top: 0;
transform-origin: 279px 278px;
text {
width: 42%;
text-align: center;
margin: 0 auto;
padding-top: 35px;
font-family: Source Han Sans CN;
font-weight: 500;
font-size: 35px;
color: #000000;
}
}
}
.go-btn {
position: absolute;
top: 234px;
left: 249px;
width: 169px;
height: 201px;
}
}
.reset-btn {
margin-top: 63px;
width: 477px;
height: 116px;
background-color: #F97E27;
border-radius: 60px;
font-size: 40px;
text-align: center;
color: #ffffff;
font-weight: bold;
}
</style>
效果图