手把手教你实现九宫格抽奖活动

您所在的位置:网站首页 九宫格抽奖图标 手把手教你实现九宫格抽奖活动

手把手教你实现九宫格抽奖活动

2023-10-13 01:31| 来源: 网络整理| 查看: 265

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!

动画2.gif

根据步骤来,一步步教你实现一个简单的九宫格抽奖动画

创建项目,引入vue Document const app = { data() { return {} }, mounted(){ }, methods:{} } Vue.createApp(app).mount('#app') 静态页面 先画底盘

主要通过两个div叠加 image.png

+ + * { + box-sizing: border-box; + padding: 0; + margin: 0; + } + .grid-box{ + width: 400px; + height: 400px; + border-radius: 16px; + background-color: #617df2; + margin: 100px auto; + padding: 15px; + } + .grid-box__inner{ + width: 100%; + height: 100%; + border-radius: 12px; + background-color: #869cfa; + } + + + + + 画奖项

通过 v-for 遍历奖项数组,利用flex布局进行排版

image.png

Document * { box-sizing: border-box; padding: 0; margin: 0; } .grid-box{ width: 400px; height: 400px; border-radius: 16px; background-color: #617df2; margin: 100px auto; padding: 15px; } .grid-box__inner{ width: 100%; height: 100%; border-radius: 12px; background-color: #869cfa; + display: flex; + flex-flow: row wrap; + align-content:flex-start } + .grid-box__item{ + width: 103px; + height: 103px; + margin-top: 15px; + margin-left: 15px; + background-color: #b8c5f2; + border-radius: 8px; + color: #fff; + display: flex; + justify-content:center; + align-items:center; + } + .grid-box__item.start-btn{ + cursor:pointer; + } + + {{ prize.label }} + + + 开始 + const app = { data() { return { + list: [ + { label: '一等奖' }, + { label: '二等奖' }, + { label: '三等奖' }, + { label: '安慰奖' }, + { label: '谢谢参与' }, + { label: '安慰奖' }, + { label: '谢谢参与' }, + { label: '三等奖' }, ] } }, mounted(){ }, methods:{} } Vue.createApp(app).mount('#app')

注意:此时奖项的顺序是按每行从头开始排的,开始按钮也不再最中间。因此进行一下小修改

画奖项(修改版) 先让所有奖项居中

image.png 移除 flex 布局,利用 position:absolute 实现居中

.grid-box__inner{ width: 100%; height: 100%; border-radius: 12px; background-color: #869cfa; + position: relative; - display: flex; - flex-flow: row wrap; - align-content:flex-start } .grid-box__item{ + position: absolute; + left: 50%; + top: 50%; + margin-left: -51.5px; + margin-top: -51.5px; width: 103px; height: 103px; - margin-top: 15px; - margin-left: 15px; background-color: #b8c5f2; border-radius: 8px; color: #fff; display: flex; justify-content:center; align-items:center; } 对每个奖项进行位移

通过transform:translate(x,y)来进行位移 位移距离为 一个奖项的宽高+间距

image.png

- + {{ prize.label }} 开始 const app = { methods:{ + getGridItemStyle(index){ + const gutter = 15 // 间距 + const width_height = 103 // 宽度 | 高度 + const margin = gutter + width_height // 偏移量 + const map = { + 0:`translate(-${margin}px,-${margin}px)`, + 1:`translate( 0px,-${margin}px)`, + 2:`translate( ${margin}px,-${margin}px)`, + 3:`translate( ${margin}px,0px)`, + 4:`translate(${margin}px,${margin}px)`, + 5:`translate(0px,${margin}px)`, + 6:`translate(-${margin}px,${margin}px)`, + 7:`translate(-${margin}px,0px)`, + } + return { + transform:map[index] || '' + } } } } 选中样式

image.png

通过切换class来实现选中样式

+ .grid-box__item.active{ + background-color: #7074f6; + } - + {{ prize.label }} 开始 const app = { data() { return { + curIndex:0, } }, } 旋转动画

思路:通过定时器setTimeout改变curIndex的值来实现动画

绑定点击事件 - + 开始 const app = { data() { return { + isTurning:false, } }, methods:{ + handleClickStartBtn(){ + if(this.isTurning) return + this.turn() + }, + turn(){} } } 模拟中奖 const app = { methods:{ + getWinningIndex(){ + return parseInt(Math.random() * 8, 10) + }, } } 抽奖动画

动画2.gif

const app = { methods:{ turn(){ + const winningIndex = this.getWinningIndex() + let index = 0 + this.curIndex = 0 + this.isTurning = true + let setTime = ()=>{ + setTimeout(()=>{ + // 至少转3圈 + if(this.curIndex==winningIndex && parseInt(index/8)===3){ + console.log('中奖了,奖品为:'+ this.list[this.curIndex].label) + this.isTurning = false + }else{ + index++ + this.curIndex = index%8 + setTime() + } + },200) + } + setTime() }, } } 抽奖动画(变速)

动画2.gif 累计动画跳动的次数,通过判断当前跳动次数 和 到达指定奖项需要跳动的总次数,当差值小于指定次数时开始减速。通过动态设置 setTimeout 的 time 来实现减速

const app = { methods:{ turn(){ const winningIndex = this.getWinningIndex() this.curIndex = 0 // 重置curIndex this.isTurning = true const lastSpeed = 600 // 最终速度( 速度 ==> setTimeout 的 延迟时间) const startSpeed = 80 // 初始速度 const count = 4 // 转的圈数 const speedDownNum = 15 // 倒数第 speedDownNum 次开始减速 const speed = (lastSpeed - startSpeed) / speedDownNum // 平均每次减速的量 let index = 0 // 变换的次数 let time = startSpeed // setTimeout 的 延迟时间 // 通过动态修改 setTimeout 的延迟时间 来达到变换速度的效果 let setTime = ()=> { setTimeout(() => { // 判断是否开始减速 if (index >= count * 8 + winningIndex - speedDownNum) { time += speed } index++ this.curIndex = index % 8 // 当 index 小于 总数时 设置下一次 timeout if (index < count * 8 + winningIndex) { setTime() } else { this.isTurning = false console.log('中奖了,奖品为:'+ this.list[this.curIndex].label) } }, time) } setTime() }, } } 完整代码 Document * { box-sizing: border-box; padding: 0; margin: 0; } .grid-box{ width: 400px; height: 400px; border-radius: 16px; background-color: #617df2; margin: 100px auto; padding: 15px; } .grid-box__inner{ width: 100%; height: 100%; border-radius: 12px; background-color: #869cfa; position: relative; } .grid-box__item{ position: absolute; left: 50%; top: 50%; margin-left: -51.5px; margin-top: -51.5px; width: 103px; height: 103px; background-color: #b8c5f2; border-radius: 8px; color: #fff; display: flex; justify-content:center; align-items:center; } .grid-box__item.active{ background-color: #7074f6; } .grid-box__item.start-btn{ cursor:pointer; } {{ prize.label }} 开始 const app = { data() { return { list: [ { label: '一等奖' }, { label: '二等奖' }, { label: '三等奖' }, { label: '安慰奖' }, { label: '谢谢参与' }, { label: '安慰奖' }, { label: '谢谢参与' }, { label: '三等奖' }, ], curIndex:null, isTurning:false } }, mounted(){ }, methods:{ getGridItemStyle(index){ const gutter = 15 // 间距 const width_height = 103 // 宽度 | 高度 const margin = gutter + width_height const map = { 0:`translate(-${margin}px,-${margin}px)`, 1:`translate( 0px,-${margin}px)`, 2:`translate( ${margin}px,-${margin}px)`, 3:`translate( ${margin}px,0px)`, 4:`translate(${margin}px,${margin}px)`, 5:`translate(0px,${margin}px)`, 6:`translate(-${margin}px,${margin}px)`, 7:`translate(-${margin}px,0px)`, } return { transform:map[index] || '' } }, handleClickStartBtn(){ if(this.isTurning) return this.turn() }, turn(){ const winningIndex = this.getWinningIndex() this.curIndex = 0 this.isTurning = true const lastSpeed = 600 // 最终速度( 速度 ==> setTimeout 的 延迟时间) const startSpeed = 80 // 初始速度 const count = 4 // 转的圈数 const speedDownNum = 15 // 倒数第 speedDownNum 次开始减速 const speed = (lastSpeed - startSpeed) / speedDownNum // 平均每次减速的量 let index = 0 // 变换的次数 let time = startSpeed // setTimeout 的 延迟时间 // 通过动态修改 setTimeout 的延迟时间 来达到变换速度的效果 let setTime = ()=> { setTimeout(() => { // 判断是否开始减速 if (index >= count * 8 + winningIndex - speedDownNum) { time += speed } index++ this.curIndex = index % 8 // 当 index 小于 总数时 设置下一次 timeout if (index < count * 8 + winningIndex) { setTime() } else { this.isTurning = false console.log('中奖了,奖品为:'+ this.list[this.curIndex].label) } }, time) } setTime() }, getWinningIndex(){ return parseInt(Math.random() * 8, 10) }, } } Vue.createApp(app).mount('#app') 码上掘金



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3