Created
January 29, 2018 01:27
-
-
Save xiispace/6b579e1cd879fc934c72f9a36a5d57f6 to your computer and use it in GitHub Desktop.
js大轮盘抽奖代码
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
/** | |
* Date: 2017/8/18 | |
* Email: [email protected] | |
* Author: hishion | |
* | |
* [Lottery 大转盘抽奖js插件, 无依赖, 简单易用] | |
* @param {[Dom Object]} oCanvas [canvas对象] | |
* @param {[Object]} options [配置参数, 请参考底部的_setOptions方法中的config对象] | |
*/ | |
function Lottery(){ | |
return this._init.apply(this, arguments); | |
} | |
Lottery.prototype = { | |
_init: function(oCanvas, options){ | |
if(!oCanvas)return false; | |
this.oCanvas = oCanvas; | |
this.options = this._setOptions(options); | |
this.size = (this.options.products || []).length; | |
this.angle = 2 * Math.PI / this.size; | |
this.sAngle = 1.5*Math.PI - this.angle/2; | |
this.ctx = oCanvas.getContext("2d"); | |
this.rotate = 0; | |
/*存储图片元素*/ | |
this.oImages = []; | |
/*存储图片链接*/ | |
this.imgUrl = []; | |
this.isOver = true; | |
this._setLayout(); | |
this._fixOptions(); | |
this._draw(); | |
this._start(); | |
//this._resize(); | |
}, | |
/*修正options参数*/ | |
_fixOptions: function(){ | |
this.options.dpr = this.options.dpr || 1; | |
this.outerRadius = parseInt(this.options.outerRadius) || this.radius; | |
this.innerRadius = parseInt(this.options.innerRadius) || 0; | |
this.options.speed = Math.min(Math.max(5, this.options.speed), 30); | |
if(String(this.options.font.y).indexOf('%') > 0){ | |
this.options.font.y = this.outerRadius * parseInt(this.options.font.y)/100; | |
} | |
if(String(this.options.images.y).indexOf('%') > 0){ | |
this.options.images.y = this.outerRadius * parseInt(this.options.images.y)/100; | |
} | |
}, | |
/*重置canvas尺寸*/ | |
_setLayout: function(){ | |
var oCanvas = this.oCanvas; | |
var options = this.options; | |
var iWidth = oCanvas.offsetWidth; | |
oCanvas.width = iWidth; | |
oCanvas.height = iWidth; | |
oCanvas.style.height = iWidth + 'px'; | |
this.diameter = iWidth; | |
this.radius = iWidth/2; | |
this.prefix('transition', this.options.transition); | |
}, | |
/*获取文字的样式*/ | |
_getFontStyle: function(){ | |
var dpr = this.options.dpr; | |
var fontStyle = this.options.font; | |
return '{{style}} {{weight}} {{size}}/{{lineHeight}} {{family}}'.replace(/\{\{([^}]*)\}\}/g, function(a, b){ | |
return b == 'size' ? parseInt(fontStyle[b]) * dpr + 'px' : fontStyle[b]; | |
}) | |
}, | |
/*重置窗口*/ | |
/* _resize: function(){ | |
var self = this; | |
window.addEventListener('resize', function(){ | |
self._setLayout(); | |
self._fixOptions(); | |
self._draw(); | |
}, false); | |
},*/ | |
/*画扇形*/ | |
_drawArc: function(){ | |
this.ctx.save(); | |
var fillStyle = this.options.fillStyle; | |
for(var i = 0; i < this.size; i++){ | |
var sAngle = this.sAngle + this.angle*i; | |
this.ctx.beginPath(); | |
this.ctx.fillStyle = fillStyle[i%fillStyle.length]; | |
this.ctx.arc(this.radius, this.radius, this.innerRadius, sAngle, sAngle + this.angle, false); | |
this.ctx.arc(this.radius, this.radius, this.outerRadius, sAngle + this.angle, sAngle, true); | |
this.ctx.closePath(); | |
this.ctx.fill(); | |
} | |
this.ctx.restore(); | |
}, | |
/*画扇形上的文字*/ | |
_drawText: function(){ | |
var fonts = this.options.font; | |
for(var i = 0; i < this.size; i++){ | |
var textArr = this._cleverBreak(this.options.products[i].name); | |
this.ctx.save(); | |
this.ctx.translate(this.radius, this.radius); | |
this.ctx.rotate(this.angle * i); | |
this.ctx.fillStyle = fonts.color; | |
this.ctx.font = this._getFontStyle(); | |
this.ctx.fillText(textArr[0], -this.ctx.measureText(textArr[0]).width/2, - fonts.y); | |
if(textArr[1]){ | |
this.ctx.fillText(textArr[1], -this.ctx.measureText(textArr[1]).width/2, -(fonts.y - 3 - (parseInt(fonts.size)||12))); | |
} | |
this.ctx.restore(); | |
this.options.products[i].imgUrl && this.imgUrl.push(this.options.products[i].imgUrl); | |
} | |
}, | |
/*文字断行*/ | |
_cleverBreak: function(str){ | |
var res, keys = this.options.breakText; | |
if(!str){return res} | |
for(var i = 0; i < keys.length; i++){ | |
var idx = str.indexOf(keys[i]); | |
if(idx > -1){ | |
res = [str.substr(0, idx), str.substr(idx)]; | |
break; | |
} | |
} | |
return res || [str]; | |
}, | |
/*绘制图片*/ | |
_drawImg: function(){ | |
var self = this, | |
width = this.options.images.width, | |
height = this.options.images.height; | |
this._loadImg(this.imgUrl, function(img){ | |
for(var i = 0; i < img.length; i++){ | |
var ret = img[i], | |
w = (width || ret.width) * self.options.dpr, | |
h = (height || ret.height) * self.options.dpr; | |
self.ctx.save(); | |
self.ctx.translate(self.radius, self.radius); | |
self.ctx.rotate(self.angle * i); | |
self.ctx.drawImage(ret, -w/2 , -self.options.images.y, w, h); | |
self.ctx.restore(); | |
}; | |
}); | |
}, | |
/*绘制画布*/ | |
_draw: function(){ | |
var options = this.options, | |
products = options.products, | |
cx = this.cx, imgArr = []; | |
this.ctx.clearRect(0, 0, this.diameter, this.diameter); | |
this._drawArc(); | |
this._drawText(); | |
this._drawImg(); | |
}, | |
/*加载要绘制的图片*/ | |
_loadImg: function(srcArr, callback){ | |
var img = document.createElement('img'); | |
var cur = cur || 0; | |
var self = this; | |
if(!self.cur){ | |
self.cur = 0; | |
self.oImages = []; | |
} | |
var src = srcArr[self.cur++]; | |
img.src = src + '?' + self.cur; | |
img.onload = function(){ | |
self.oImages.push(this); | |
if(self.cur < srcArr.length){ | |
self._loadImg(srcArr, callback); | |
}else{ | |
self.cur = false; | |
callback(self.oImages); | |
} | |
this.onload = false; | |
}; | |
img.onerror = function(){ | |
//console.log(this.src); | |
} | |
}, | |
/*开始旋转转盘*/ | |
_beginRotate: function(){ | |
var self = this, iSpeed = this.options.speed; | |
self.isOver = false; | |
clearInterval(self.timer); | |
self.timer = setInterval(function(){ | |
self.setRotateStyle(self.rotate + iSpeed); | |
self.rotate += iSpeed; | |
}, 30); | |
}, | |
/*开始抽奖*/ | |
_start: function(){ | |
var self = this; | |
if(!this.options.handler)return; | |
this._fastClick(this.options.handler, function(ev){ | |
if(self.hasClass(this, 'disabled'))return; | |
if(self.isOver){ | |
self._beginRotate(); | |
typeof self.options.handlerCallback === 'function' && self.options.handlerCallback.call(this, self); | |
} | |
}); | |
}, | |
_off: function(elemet, eventType, callback){ | |
elemet.removeEventListener(eventType, callback, false); | |
}, | |
_fastClick: function(elemet, callback){ | |
if('ontouchstart' in document){ | |
elemet.addEventListener('touchstart', callback, false); | |
}else{ | |
elemet.addEventListener('click', callback, false); | |
} | |
}, | |
/*简单的继承*/ | |
extend: function(source, distance){ | |
for(var attr in distance){ | |
if(distance[attr] !== undefined){ | |
source[attr] = distance[attr]; | |
} | |
} | |
return source; | |
}, | |
/*设置旋转*/ | |
setRotateStyle: function(rotate){ | |
this.prefix('transform', 'rotate(' + rotate + 'deg)'); | |
}, | |
prefix: function(attr, val){ | |
var _fix = ['moz', 'o', 'webkit'], self = this; | |
_fix.map(function(item){ | |
self.oCanvas.style[item + self.capitalize(attr)] = val; | |
}); | |
self.oCanvas.style[attr] = val; | |
}, | |
capitalize: function(str){ | |
return str.substr(0, 1).toUpperCase() + str.substr(1); | |
}, | |
/*判断指定className是否存在*/ | |
hasClass: function(elemet, className){ | |
var cls = elemet.className; | |
return !!cls.match(new RegExp('\\b' + className + '\\b')); | |
}, | |
/*停止转动, idx为指定停止的位置*/ | |
stop: function(idx, callback){ | |
if(this.options.interval > 0){ | |
this._stop(idx, function(_interface){ | |
_interface.isOver = false; | |
_interface.intervalTimer = setTimeout(function(){ | |
_interface.isOver = true; | |
callback && callback(_interface); | |
}, _interface.options.interval) | |
}); | |
}else{ | |
this._stop.apply(this, arguments); | |
} | |
}, | |
_stop: function(idx, callback){ | |
var stopTimer = null, self = this, iAngle = 360/self.size; | |
var iTarget = self.rotate + 360*5 + (self.size - idx - self.rotate%360/iAngle) * iAngle; | |
var speedRatio = 35 - this.options.speed; | |
this.timer && clearInterval(this.timer); | |
function move(){ | |
var iSpeed = (iTarget - self.rotate)/speedRatio; | |
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); | |
self.rotate += iSpeed; | |
self.rotate >= iTarget && (self.rotate = iTarget, self.isOver = true); | |
self.setRotateStyle(self.rotate); | |
if(self.isOver){clearInterval(stopTimer); callback && callback(self);} | |
} | |
stopTimer = setInterval(move, 45); | |
}, | |
/*设置配置项*/ | |
_setOptions: function(options){ | |
/*默认配置项*/ | |
var config = { | |
/*点击抽奖元素*/ | |
handler: '', | |
/*点击抽奖的回调*/ | |
handlerCallback: function(_interface){}, | |
outerRadius: 243, | |
innerRadius: 0, | |
/*循环填充数组颜色*/ | |
fillStyle: ['#f5fcfc', '#ffffff'], | |
/*请参考 flexible*/ | |
dpr: 1, | |
/*重复触发的间距时间*/ | |
interval: 1000, | |
/*速度5-30越大越快*/ | |
speed: 8, | |
/*canvas css3运动样式*/ | |
transition: 'transform .3s linear', | |
/*字体位置与样式*/ | |
font: { | |
y: '50%', | |
color: '#0BA6AA', | |
style: 'normal', | |
weight: 500, | |
size: '14px', | |
lineHeight: 1, | |
family: 'Arail' | |
}, | |
/*图片位置与尺寸*/ | |
images: { | |
y: '90%', | |
width: 32, | |
height: 32 | |
}, | |
/*打断文字换行*/ | |
breakText: ['金币', '京东卡', '大秘笈', '大礼包', '(', '参与', '极客', '定制'], | |
/*礼物*/ | |
products: [ | |
] | |
}; | |
return this.extend(config, options); | |
} | |
}; | |
window.Lottery = Lottery; | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment