码上敲享录 > 最全面的HTML入门教程 > 实现抽奖大转盘html完整页面分享

实现抽奖大转盘html完整页面分享

上一章章节目录 2021-08-10已有1170人阅读 评论(0)

实现抽奖大转盘html完整页面分享


解决方法:

创建一个html页面,复制以下html页面替换后用浏览器打开预览效果,点击转盘中心模拟抽奖,中心看不到指针是因为没有./images/handler.png图片

<!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>

(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: 120,

           /*运动最少持续时间*/

           duration: 3000,

           /*字体位置与样式*/

           /*画布显示缩放比例,值为1 安卓模糊*/

           scale: this.ua.isIos ? 2 : 2,

           /*字体样式,浅拷贝 需整个font对象传入*/

           font: {

               y: '50%',

               color: '#ee6500',

               /*循环填充字体颜色*/

               //color: ['#f00', '#ee6500'],

               style: 'normal',

               weight: 500,

               size: '14px',

               lineHeight: 1,

               family: 'Arail'

           },

           /*图片位置与尺寸*/

           images: {

               y: '88%',

               width: 32,

               height: 32

           },

           /*打断文字换行*/

           breakText: ['金币', '红包'],

           /*礼物*/

           products: [

               /*{

                   imgUrl: 'http://',

                   text: '苹果手机',

               }*/

           ]

       };

       return this.extend(config, options);

   }

};


window.Lottery = Lottery;

}());




/*模拟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": "20元话费"

   },

   {

       "imgUrl": "./images/redpacket.png",

       "name": "50元话费"

   },

   {

       "imgUrl": "./images/redpacket.png",

       "name": "100元话费"

   },

   {

       "imgUrl": "./images/redpacket.png",

       "name": "谢谢惠顾"

   }

];


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>

向大家推荐《Activiti工作流实战教程》:https://xiaozhuanlan.com/activiti
0

有建议,请留言!

  • *您的姓名:

  • *所在城市:

  • *您的联系电话:

    *您的QQ:

  • 咨询问题:

  • 提 交