用以下知识,整个指针会动,有灯光交替闪烁,能实现页面刷新初始化的大转盘
2条回答 默认 最新
- 啊泮 2023-05-19 18:16关注
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"> <title>大转盘抽奖</title> <style> *{ margin: 0; padding: 0; } #lottery-wrap{ position: relative; display: block; margin: 150px auto; width: 300px; border: 8px solid #eac34c; border-radius: 50%; box-shadow: 3px 0 3px #fffdc9, 0px 3px 3px #fffdc9, -3px 0 3px #fffdc9, 0px -3px 3px #fffdc9; } canvas{ display: block; } #lottery-handler{ position: absolute; z-index: 2; width: 60px; height: 74px; left: 50%; top: 50%; margin: -44px 0 0 -30px; background: url(./images/handler.png) no-repeat 50%; background-size: contain; } </style> </head> <body style="background-color: darkkhaki;"> <div id="lottery-wrap"> <div id="lottery-handler"></div> <canvas width="300" height="300" id="lottery"></canvas> </div> <script src="./Lottery.js"></script> <script> /*模拟ajax请求数据返回*/ function _ajax(callback){ /*jQuery.ajax({ url: url, data: data, success: function(response){ callback && callback(response); } })*/ setTimeout(function(){ var _index = Math.floor(Math.random()*4);//此处是概率,可自己写算法定义概率 var response = {id: 1, name: products[_index].name, index: _index}; callback && callback(response); }, 100); } //此处是定义的奖项 var products = [ { "imgUrl": "./images/redpacket.png", "name": "10元红包" }, { "imgUrl": "./images/redpacket.png", "name": "20元红包" }, { "imgUrl": "./images/redpacket.png", "name": "50元红包" }, { "imgUrl": "./images/redpacket.png", "name": "100元红包" } ]; new Lottery(document.getElementById('lottery'), { handler: document.getElementById('lottery-handler'), handlerCallback: function(_interface){ /*ajax获取中奖结果*/ _ajax(function(response){ console.log(response); /*指定停止的位置:索引*/ _interface.stop(response.index, function(){ alert('恭喜你中得:' + response.name) }); }); }, images: { width: 22, height: 29, y: '88%', }, products: products }); </script> </body> </html>
(function(){ /** * * [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(); }, /*修正options参数*/ _fixOptions: function(){ this.outerRadius = parseInt(this.options.outerRadius) || this.radius; this.innerRadius = parseInt(this.options.innerRadius) * this.options.scale || 0; this.options.speed = Math.min(Math.max(1, 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 diameter = oCanvas.offsetWidth || oCanvas.clientWidth || oCanvas.width; oCanvas.style.height = diameter + 'px'; oCanvas.style.width = diameter + 'px'; diameter = diameter * this.options.scale; this.diameter = oCanvas.width = oCanvas.height = diameter; this.radius = diameter/2; }, /*获取文字的样式*/ _getFontStyle: function(){ var scale = this.options.scale; var fontStyle = this.options.font; return '{{style}} {{weight}} {{size}}/{{lineHeight}} {{family}}'.replace(/\{\{([^}]*)\}\}/g, function(a, b){ return b == 'size' ? parseInt(fontStyle[b]) * scale + 'px' : fontStyle[b]; }) }, /*画扇形*/ _drawArc: function(){ this.ctx.save(); var fillStyle = this.options.fillStyle; if(!fillStyle)return; 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(); }, isArray: function(arr){ return arr && Object.prototype.toString.call(arr) == '[object Array]'; }, /*画扇形上的文字*/ _drawText: function(){ var fonts = this.options.font; var scale = this.options.scale; 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 = this.isArray(fonts.color) ? fonts.color[i%fonts.color.length] : fonts.color; this.ctx.font = this._getFontStyle(); this.ctx.fillText(textArr[0], -this.ctx.measureText(textArr[0]).width/2, - fonts.y); if(textArr[1]){ var y = -(fonts.y-(parseInt(fonts.size)*scale*this.options.font.lineHeight)); this.ctx.fillText(textArr[1], -this.ctx.measureText(textArr[1]).width/2, y); } 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){ var scale = self.options.scale; for(var i = 0; i < img.length; i++){ var ret = img[i], w = (width || ret.width) * scale, h = (height || ret.height) * scale; 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, cSpeed = 0, is = 0, iSpeed = this.options.speed; self.cSpeed = 0; self.isOver = false; clearInterval(self.timer); self.timer = setInterval(function(){ is = (iSpeed-cSpeed)/iSpeed; is = is > 0 ? Math.ceil(is) : Math.floor(is); cSpeed += is; if(cSpeed>iSpeed){ is = iSpeed; } self.cSpeed = cSpeed; self.rotate += cSpeed; self.setRotateStyle(self.rotate); }, 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.sTime = self.now(); 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){ if(!val)return; 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){ var iTime = Math.max(0, this.options.duration - this.now() + this.sTime); var self = this, durTimer = null; durTimer = setTimeout(function(){ if(self.options.interval > 0){ self._stop(idx, function(_interface){ _interface.isOver = false; _interface.intervalTimer = setTimeout(function(){ _interface.isOver = true; clearTimeout(_interface.intervalTimer); callback && callback(_interface); }, _interface.options.interval) }); }else{ self._stop.apply(self, arguments); } clearTimeout(durTimer); }, iTime); }, _stop: function(idx, callback){ var stopTimer = null, self = this, iAngle = 360/self.size; var iTarget = self.rotate + 360*4 + (self.size - idx - self.rotate%360/iAngle) * iAngle; var iSpeed = this.options.speed; this.timer && clearInterval(this.timer); function move(){ var cSpeed = (iTarget - self.rotate)/iSpeed; cSpeed = cSpeed > 0 ? Math.ceil(cSpeed) : Math.floor(cSpeed); if(cSpeed > self.cSpeed){ cSpeed = self.cSpeed; } self.rotate += cSpeed; self.rotate >= iTarget && (self.rotate = iTarget, self.isOver = true); self.setRotateStyle(self.rotate); if(self.isOver){clearInterval(stopTimer); callback && callback(self);} } stopTimer = setInterval(move, 30); }, now: function(){ return new Date() - 0; }, ua: { isIos: /iphone|ipad/i.test(navigator.userAgent), isAndroid: /android/i.test(navigator.userAgent) }, /*设置配置项*/ _setOptions: function(options){ /*默认配置项*/ var config = { /*点击抽奖元素*/ handler: '', /*点击抽奖的回调*/ handlerCallback: function(_interface){}, outerRadius: '', innerRadius: 0, /*循环填充数组颜色*/ fillStyle: ['#ffdf8a', '#fffdc9'], /*重复触发的间距时间*/ interval: 1000, /*速度越大越快*/ speed: 12, /*运动最少持续时间*/ duration: 3000, /*字体位置与样式*/ /*画布显示缩放比例,值为1 安卓模糊*/ scale: this.ua.isIos ? 2 : 2, /*字体样式,浅拷贝 需整个font对象传入*/ font: { y: '50%', color: '#ee6500', /*循环填充字体颜色*/ //color: ['#f00', '#ee6500'], style: 'normal', weight: 500, size: '10px', lineHeight: 1, family: 'Arail' }, /*图片位置与尺寸*/ images: { y: '88%', width: 32, height: 32 }, /*打断文字换行*/ breakText: ['金币', '红包'], /*礼物*/ products: [ /*{ imgUrl: 'http://', text: '苹果手机', }*/ ] }; return this.extend(config, options); } }; window.Lottery = Lottery; }());
解决 无用评论 打赏 举报
悬赏问题
- ¥15 AD9164瞬时带宽1.8G,怎么计算出来?
- ¥20 为什么安装CSiBridge时出现了这个问题,尝试了很多方法都不行,求详细操作步骤?
- ¥15 鼠标右键,撤销删除 复制 移动,要怎样删除
- ¥15 使用MATLAB进行余弦相似度计算加速
- ¥15 服务器安装php5.6版本
- ¥15 我想用51单片机和数码管做一个从0开始的计数表 我写了一串代码 但是放到单片机里面数码管只闪烁一下然后熄灭
- ¥20 系统工程中,状态空间模型中状态方程的应用。请猛男来完整讲一下下面所有问题
- ¥15 我想在WPF的Model Code中获取ViewModel Code中的一个参数
- ¥15 arcgis处理土地利用道路 建筑 林地分类
- ¥20 使用visual studio 工具用C++语音,调用openslsx库读取excel文件的sheet问题