一回頭, 12月中旬了。 最近項目忙,還被封閉了半個月。
爲了保持一個月1到2篇博客,月中了,就說說上次寫的抽獎吧。html
這裏講的是九宮格抽獎,其實圓盤的那種都相似。
在線demo地址
在線代碼地址git
邏輯github
從上能夠看出來,其實你中獎不中獎是服務來決定的,前臺那一些絢麗的動畫,就是給你帶來快感的。app
這裏咱們要先封裝一個抽獎的對象,把抽獎自己的一些邏輯分離出來,和DOM等等不要有半毛錢關係。dom
定義Lottery
對外方法:函數
Lottery初始化參數動畫
內部參數this
再額外提兩個方prototype
Lottery.prototype.emit = function (type) { var params = slice.call(arguments); var restParams = params.slice(1); var type = params[0]; var method = this['on' + type]; if ($.isFunction(method)) { method.apply(this, restParams); } }
Lottery.prototype.innerStart = function (cb) { var that = this; var next = function () { that.next(function () { cb && cb(next); }) } next() } Lottery.prototype.next = function (cb) { var interval = this.getInterval(); this.ticketId = setTimeout(cb, interval); }
到這裏其實,你們都基本明白了怎麼實現了吧。
rest
附上Lottery源碼
(function () { var defaultOption = { startIndex: 0, // 初始位置 pits: 8, // 當前位置 interval: 100, // 初始間隔 rate: 1.5, // 係數 cycle: 20, //轉動基本次數:即至少須要轉動多少次再進入抽獎環節 getInterval: null // 自定義旋轉間隔函數 //onStart: null, // 當開始 //onUpdate: null, // 旋轉一次 //onEnded: null, // 結束 //onError: null // 異常, 好比轉動次數已經達到設定值, 可是沒有設置獎項 }; var slice = Array.prototype.slice; function Lottery(options) { this.originOptions = options; this.options = $.extend({}, defaultOption, options); // 定時器Id this.ticketId = null; // 獎項 this.prizeIndexes = null; // 轉動次數 this.times = 0; // 當前位置 this.index = 0; // 模擬結果 this.animatingResult = false; // 實際的轉動基本次數, 大於開始中獎 this.cycle = this.options.cycle; // 進行中 this.processing = false; // 上次轉動時間 this.lastTime = null; } Lottery.prototype.start = function () { if (this.processing) { return } this.processing = true; // 增長隨機數 this.cycle = this.options.cycle + Math.floor(Math.random() * 10); this.emit('Start', this, this.index, this.cycle); this.lastTime = Date.now(); var that = this; this.innerStart(function (next) { if (that.animatingResult) { that.times++; } that.index = (that.index + 1) % that.options.pits; var continu = that.judge(); if (!continu) { that.stop(); return } that.printInfo(); that.emit('Update', that, that.index, that.times); next(); }) } Lottery.prototype.judge = function () { var cycle = this.cycle; var times = this.times; // 到達旋轉次數 if (times > cycle) { // 沒有設置獎項 if (!$.isArray(this.prizeIndexes)) { this.emit('Error', this, 404, '未設置獎項'); return false; } if (this.prizeIndexes.indexOf(this.index) >= 0) { this.emit('Ended', this, this.index, this.prizeIndexes); return false; } } return true; } Lottery.prototype.emit = function (type) { var params = slice.call(arguments); var restParams = params.slice(1); var type = params[0]; var method = this['on' + type]; if ($.isFunction(method)) { method.apply(this, restParams); } } Lottery.prototype.stop = function () { this.clearJob(); this.animatingResult = false; this.ticketId = null; this.prizeIndexes = null; this.times = 0; this.processing = false; } Lottery.prototype.getInterval = function () { const getIntervalFn = this.options; if ($.isFunction(getIntervalFn)) { return getIntervalFn(this, this.index, this.times, this.cycle); } else { return Math.floor(this.options.interval * Math.pow(this.options.rate, this.times / 10)); } } Lottery.prototype.clearJob = function () { clearTimeout(this.ticketId); } Lottery.prototype.innerStart = function (cb) { var that = this; var next = function () { that.next(function () { cb && cb(next); }) } next() } Lottery.prototype.next = function (cb) { var interval = this.getInterval(); this.ticketId = setTimeout(cb, interval); } Lottery.prototype.reset = function () { this.stop(); this.options = $.extends({}, defaultOption, this.originOptions); this.index = 0; } Lottery.prototype.setPrize = function (prizeIndexes) { if (this.animatingResult) { return } this.prizeIndexes = prizeIndexes; // 設置值後, 開始模擬中獎 this.animatingResult = true } Lottery.prototype.printInfo = function () { var now = Date.now(); console.log('index:', this.index, 'times:', this.times, 'cycle:', this.cycle, 'interval:', now - this.lastTime); this.lastTime = now; } window.Lottery = Lottery })()