老规矩,先看下静态UI,以便于有个图像概念
将指针和中奖区域划分两部分,目前常规的效果,控制中奖区域旋转,然后停在指针处,当然控制指针也可以,一套思路,dom结构也比较简单,唯一算是复杂点的就是中奖区域,但是如果你足够懒,像我一样,你可以传递一张图也可以,完全依赖远端数据;
每个移动位置应均分,360/个数 === 每个奖品所占据的位置,以本文为例8个奖品位置,每个区域应为45deg,每个指针中心位置应为±22.5deg(±的意思看你是顺时针还是逆时针)具体值看下面 实现逻辑 区域
// 基础参数 data () { return { isrun: false, rotateAngle: 0, // 旋转角度 config: { duration: 4000, // 总旋转时间 ms级 circle: 8, // 旋转圈数 mode: 'ease-in-out' // 由快到慢 惯性效果都省了 }, cricleAdd: 1, // 第几次抽奖 drawIndex: 0 // 中奖索引 转盘图片排序 指针右手开始 0-... } } // 计算属性 computed: { rotateStyle () { const _c = this.config return ` -webkit-transition: transform ${_c.duration}ms ${_c.mode}; transition: transform ${_c.duration}ms ${_c.mode}; -webkit-transform: rotate(${this.rotateAngle}deg); transform: rotate(${this.rotateAngle}deg);` } } // 入参 props: { httpData: {}, // 接口调用所需参数 stateData: { type: Object, default: () => { return { coin: 0, // 超级币数量 prize_img: '' // 转盘图片 } } } }
this.rotateAngle = this.config.circle * 360 * this.cricleAdd - (22.5 + this.drawIndex * 45) // 圈数位置解析 // this.config.circle * 360 * this.cricleAdd 顺时针总圈数/累积总圈数 // 22.5 + this.drawIndex * 45 ===> (奖品位置 === this.drawIndex * 45) (指针中间位置 === 22.5)
this.$emit('draw_fin', 'start') this.$emit('draw_fin', 'fin')
methods: { async run () { if (this.stateData.coin < 10) { console.log('超级币不足') return } if (this.isrun) return // const data = await this.goDraw() // 可以作为弹窗等信息展示 this.$emit('draw_fin', 'start') this.$set(this.stateData, 'coin', 0) // 更新数据,此处仅为示例,推荐使用 draw_fin方法的 start/fin 进行相应数据更新 this.isrun = true this.rotateAngle = this.config.circle * 360 * this.cricleAdd - (22.5 + this.drawIndex * 45) // 圈数位置解析 // this.config.circle * 360 * this.cricleAdd 顺时针总圈数/累积总圈数 // 22.5 + this.drawIndex * 45 ===> (奖品位置 === this.drawIndex * 45) (指针中间位置 === 22.5) this.cricleAdd++ setTimeout(() => { this.$emit('draw_fin', 'fin') this.isrun = false }, this.config.duration) }, goDraw () { // 请求接口拿到中奖商品 // 加下自己项目的样式 loading 用户体验 return new Promise(async (resolve, reject) => { // await 奖品接口 resolve({ msg: '抽奖明细' }) }) }
使用
import dialWrap from '../../components/dial/dial.vue' <dialWrap ref="dialWrap" :stateData="stateData"></dialWrap>