UNPKG

ant-mini-fruit-slots

Version:

支付宝小程序大转盘组件

136 lines (129 loc) 4.87 kB
Component({ data: { activeOrder: [0, 1, 2, 4, 7, 6, 5, 3], // 九宫格除按钮外的8个格子自左上角顺时针的下标顺序 activeIndex: NaN, itemWidth: 0, isRolling: false }, props: { width: 700, // 组件宽度,单位 rpx margin: 20, // 奖项之间的外边距,单位 rpx prizeList: [], // 奖项列表,个数限定为8 prizeName: '', // 获奖项名称 rollTimes: 3, // 转动圈数 mode: 'pre', // 抽奖模式:pre(默认) | realtime currentIndex: 0, // 转动开始的下标 speed: 100, // 转动速度, 单位 ms 'class': '', // 自定义类名 disabled: false, // 按钮是否可点击 onStart: function onStart() {}, // 开始的回调 onFinish: function onFinish() {} // 结束的回调 }, didMount: function didMount() { this.prizeLength = 8; // 必须要取整,否则部分机型下有适配问题 this.setData({ itemWidth: parseInt((this.props.width - 4 * this.props.margin) / 3) }); }, didUpdate: function didUpdate(prevProps) { var _props = this.props, mode = _props.mode, prizeName = _props.prizeName; if (mode === 'realtime' && prizeName && prevProps.prizeName !== prizeName) { var prizeIndex = this.findPrizeIndex(prizeName); if (prizeIndex === -1) { console.error('请传入正确的获奖项name,其值必须存在于 prizeList name 字段中'); return; } // 总转动步数 = 默认圈数 x 奖品个数 + 结束位置索引 + 当前位置到一圈结束还剩下的步数 var activeIndex = this.currentStep % this.prizeLength; this.totalSteps = 1 * this.prizeLength + this.currentStep + (this.prizeLength - activeIndex) + prizeIndex; } }, methods: { next: function next(activeIndex) { var _this = this; activeIndex = activeIndex % this.prizeLength; this.setData({ activeIndex: this.data.activeOrder[activeIndex] }); if (this.currentStep === this.totalSteps) { this.done(activeIndex); return; } this.currentStep += 1; setTimeout(function () { _this.next(++activeIndex); }, this.speedCtl()); }, /** 模拟速度变化,分为四档 当走过格子数 < 总步数 - 2圈格子数时,速度为speed 以此线性递增 */ speedCtl: function speedCtl() { var steps = this.totalSteps; var size = this.prizeLength; var currentStep = this.currentStep; if (currentStep < steps - size * 2) { return this.props.speed; } else if (steps - size * 2 <= currentStep && currentStep <= steps - size) { return this.props.speed * 2; } else if (steps - currentStep > 3) { return this.props.speed * 3; } else { return this.props.speed * 4; } }, /** 通过名称获取奖品项在顺时针格子中对应的下标 未找到返回-1 */ findPrizeIndex: function findPrizeIndex(name) { var prizeList = this.props.prizeList; var order = this.data.activeOrder; for (var i = 0; i < this.prizeLength; i++) { if (prizeList[order[i]].name === name) { return i; } } return -1; }, start: function start() { var _props2 = this.props, disabled = _props2.disabled, prizeList = _props2.prizeList, currentIndex = _props2.currentIndex, prizeName = _props2.prizeName, mode = _props2.mode; if (disabled || this.data.isRolling) return; this.currentStep = 0; if (prizeList.length !== 8) { console.error('奖品项列表 prizeList 长度不为8'); } var activeIndex = +currentIndex || 0; if (mode === 'realtime') { this.totalSteps = Infinity; } else { // 奖品项下标 var prizeIndex = this.findPrizeIndex(prizeName); if (prizeIndex === -1) { console.error('请传入正确的获奖项name,其值必须存在于 prizeList name 字段中'); } // 总转动步数 = 默认圈数 x 奖品个数 + 结束位置索引 + 当前位置到一圈结束还剩下的步数 this.totalSteps = this.props.rollTimes * this.prizeLength + prizeIndex + (this.prizeLength - activeIndex); } this.setData({ isRolling: true }); this.next(activeIndex); this.props.onStart(); }, done: function done(activeIndex) { var _this2 = this; // setTimeout防止抽奖结束后父组件设置disabled=true的过程中用户马上再次点击抽奖 此时 disabled 和 isRolling // 状态还没来得及更新,start 函数可能被执行 setTimeout(function () { _this2.setData({ isRolling: false }); }, 50); this.props.onFinish(activeIndex, this.props.prizeName); } } });