js抽奖转盘实现方法分析


Posted in Javascript onMay 16, 2020

本文实例讲述了js抽奖转盘实现方法。分享给大家供大家参考,具体如下:

 HTML  这里.left 固定了圆的宽度和高度,还有canvas也设置了固定宽高 绘制圆心的坐标也就出来了 (203,203)

抽奖转盘是由一个大圆和一个内圆完成 ;大圆负责绘制上奖品 ,内圆负责确定指针的位置,指针直接使用图片,决定位置确定

<div class="left">

<div class="turnplate" style="background:#1bacff;border-radius: 50%">
<canvas class="item" id="wheelcanvas" width="406px" height="406px"></canvas>
<img class="pointer" src="sp2/point.png"/>
</div>

</div>

js抽奖转盘实现方法分析

外圆留空多少的问题

PS里查看间距是多少,此处圆心(203,203) 大圆的半径就是203-10 =193

js抽奖转盘实现方法分析

这个数值在下图里设置

js抽奖转盘实现方法分析

JS

<script type="text/javascript">
    var turnplate={
      restaraunts:[],				//大转盘奖品名称
      colors:[],					//大转盘奖品区块对应背景颜色
      outsideRadius:193,			//大转盘外圆的半径 192
      textRadius:155,				//大转盘奖品位置距离圆心的距离
      insideRadius:68,			//大转盘内圆的半径
      startAngle:0,				//开始角度

      bRotate:false				//false:停止;ture:旋转
    };

    $(document).ready(function(){
      //动态添加大转盘的奖品与奖品区域背景颜色
      turnplate.restaraunts = ["50元代金券", "升职加薪", "100元代金券", "财源滚滚", "200元代金券", "爱情甜蜜 ", "500元代金券", "变美变帅"];
      turnplate.colors = ["#1b62ca", "#1bacff", "#1b62ca", "#1bacff","#1b62ca", "#1bacff", "#1b62ca", "#1bacff"];


      var rotateTimeOut = function (){
        $('#wheelcanvas').rotate({
          angle:0,
          animateTo:2160,
          duration:8000,
          callback:function (){
            alert('网络超时,请检查您的网络设置!');
          }
        });
      };

      //旋转转盘 item:奖品位置; txt:提示语;
      var rotateFn = function (item, txt){
        var angles = item * (360 / turnplate.restaraunts.length) - (360 / (turnplate.restaraunts.length*2));
        if(angles<270){
          angles = 270 - angles;
        }else{
          angles = 360 - angles + 270;
        }
        $('#wheelcanvas').stopRotate();
        $('#wheelcanvas').rotate({
          angle:0,
          animateTo:angles+1800,
          duration:8000,
          callback:function (){
            alert(txt);
            turnplate.bRotate = !turnplate.bRotate;
          }
        });
      };

      $('.pointer').click(function (){
        if(turnplate.bRotate)return;
        turnplate.bRotate = !turnplate.bRotate;
        //获取随机数(奖品个数范围内)
        var item = rnd(1,turnplate.restaraunts.length);
        //奖品数量等于10,指针落在对应奖品区域的中心角度[252, 216, 180, 144, 108, 72, 36, 360, 324, 288]
        rotateFn(item, turnplate.restaraunts[item-1]);
        /* switch (item) {
         case 1:
         rotateFn(252, turnplate.restaraunts[0]);
         break;
         case 2:
         rotateFn(216, turnplate.restaraunts[1]);
         break;
         case 3:
         rotateFn(180, turnplate.restaraunts[2]);
         break;
         case 4:
         rotateFn(144, turnplate.restaraunts[3]);
         break;
         case 5:
         rotateFn(108, turnplate.restaraunts[4]);
         break;
         case 6:
         rotateFn(72, turnplate.restaraunts[5]);
         break;
         case 7:
         rotateFn(36, turnplate.restaraunts[6]);
         break;
         case 8:
         rotateFn(360, turnplate.restaraunts[7]);
         break;
         case 9:
         rotateFn(324, turnplate.restaraunts[8]);
         break;
         case 10:
         rotateFn(288, turnplate.restaraunts[9]);
         break;
         } */
        console.log(item);
      });
    });

    function rnd(n, m){
      var random = Math.floor(Math.random()*(m-n+1)+n);
      return random;

    }


    //页面所有元素加载完毕后执行drawRouletteWheel()方法对转盘进行渲染
    window.onload=function(){
      drawRouletteWheel();
    };

    function drawRouletteWheel() {
      var canvas = document.getElementById("wheelcanvas");
      if (canvas.getContext) {
        //根据奖品个数计算圆周角度
        var arc = Math.PI / (turnplate.restaraunts.length/2);//圆周率/ 奖品数量除以2
        var ctx = canvas.getContext("2d");
        //在给定矩形内清空一个矩形
        ctx.clearRect(0,0,422,422);
        //strokeStyle 属性设置或返回用于笔触的颜色、渐变或模式
        ctx.strokeStyle = "#FFBE04";
        //font 属性设置或返回画布上文本内容的当前字体属性
        ctx.font = '16px Microsoft YaHei';
        // 绘制圆 (弧形)
        for(var i = 0; i < turnplate.restaraunts.length; i++) {
          var angle = turnplate.startAngle + i * arc;
          ctx.fillStyle = turnplate.colors[i];
          ctx.beginPath();
          //arc(x,y,r,起始角,结束角,绘制方向) 方法创建弧/曲线(用于创建圆或部分圆)
          ctx.arc(203, 203, turnplate.outsideRadius, angle, angle + arc, false);//绘制外圆
          ctx.arc(203, 203, turnplate.insideRadius, angle + arc, angle, true);//绘制内圆
          ctx.stroke();
          ctx.fill();
          //锁画布(为了保存之前的画布状态)
          ctx.save();

          //----绘制奖品开始----
          ctx.fillStyle = "#FFF";/*奖品文字颜色*/
          var text = turnplate.restaraunts[i];
          var line_height = 17;
          //translate方法重新映射画布上的 (0,0) 位置
          ctx.translate(211 + Math.cos(angle + arc / 2) * turnplate.textRadius, 211 + Math.sin(angle + arc / 2) * turnplate.textRadius);

          //rotate方法旋转当前的绘图
          ctx.rotate(angle + arc / 2 + Math.PI / 2);

          /** 下面代码根据奖品类型、奖品名称长度渲染不同效果,如字体、颜色、图片效果。(具体根据实际情况改变) **/
          if(text.indexOf("M")>0){//流量包
            var texts = text.split("M");
            for(var j = 0; j<texts.length; j++){
              ctx.font = j == 0?'bold 20px Microsoft YaHei':'16px Microsoft YaHei';
              if(j == 0){
                ctx.fillText(texts[j]+"M", -ctx.measureText(texts[j]+"M").width / 2, j * line_height);
              }else{
                ctx.fillText(texts[j], -ctx.measureText(texts[j]).width / 2, j * line_height);
              }
            }
          }else if(text.indexOf("M") == -1 && text.length>6){//奖品名称长度超过一定范围
            text = text.substring(0,6)+"||"+text.substring(6);
            var texts = text.split("||");
            for(var j = 0; j<texts.length; j++){
              ctx.fillText(texts[j], -ctx.measureText(texts[j]).width / 2, j * line_height);
            }
          }else{
            //在画布上绘制填色的文本。文本的默认颜色是黑色
            //measureText()方法返回包含一个对象,该对象包含以像素计的指定字体宽度
            ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
          }

          //添加对应图标
          if(text.indexOf("闪币")>0){
            var img= document.getElementById("shan-img");
            img.onload=function(){
              ctx.drawImage(img,-15,10);
            };
            ctx.drawImage(img,-15,10);
          }else if(text.indexOf("谢谢参与")>=0){
            var img= document.getElementById("sorry-img");
            img.onload=function(){
              ctx.drawImage(img,-15,10);
            };
            ctx.drawImage(img,-15,10);
          }
          //把当前画布返回(调整)到上一个save()状态之前
          ctx.restore();
          //----绘制奖品结束----
        }
      }
    }

  </script>

引用jquery

在加载以下JS

/* ????????????? www.datouwang.com */
(function($) {
var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform msTransform MozTransform".split(" ");
for (var a=0;a<toCheck.length;a++) if (styles[toCheck[a]] !== undefined) supportedCSS = toCheck[a];
// Bad eval to preven google closure to remove it from code o_O
// After compresion replace it back to var IE = 'v' == '\v'
var IE = eval('"v"=="\v"');

jQuery.fn.extend({
  rotate:function(parameters)
  {
    if (this.length===0||typeof parameters=="undefined") return;
      if (typeof parameters=="number") parameters={angle:parameters};
    var returned=[];
    for (var i=0,i0=this.length;i<i0;i++)
      {
        var element=this.get(i);	
        if (!element.Wilq32 || !element.Wilq32.PhotoEffect) {

          var paramClone = $.extend(true, {}, parameters); 
          var newRotObject = new Wilq32.PhotoEffect(element,paramClone)._rootObj;

          returned.push($(newRotObject));
        }
        else {
          element.Wilq32.PhotoEffect._handleRotation(parameters);
        }
      }
      return returned;
  },
  getRotateAngle: function(){
    var ret = [];
    for (var i=0,i0=this.length;i<i0;i++)
      {
        var element=this.get(i);	
        if (element.Wilq32 && element.Wilq32.PhotoEffect) {
          ret[i] = element.Wilq32.PhotoEffect._angle;
        }
      }
      return ret;
  },
  stopRotate: function(){
    for (var i=0,i0=this.length;i<i0;i++)
      {
        var element=this.get(i);	
        if (element.Wilq32 && element.Wilq32.PhotoEffect) {
          clearTimeout(element.Wilq32.PhotoEffect._timer);
        }
      }
  }
});

// Library agnostic interface

Wilq32=window.Wilq32||{};
Wilq32.PhotoEffect=(function(){

	if (supportedCSS) {
		return function(img,parameters){
			img.Wilq32 = {
				PhotoEffect: this
			};
      
      this._img = this._rootObj = this._eventObj = img;
      this._handleRotation(parameters);
		}
	} else {
		return function(img,parameters) {
			// Make sure that class and id are also copied - just in case you would like to refeer to an newly created object
      this._img = img;

			this._rootObj=document.createElement('span');
			this._rootObj.style.display="inline-block";
			this._rootObj.Wilq32 = 
				{
					PhotoEffect: this
				};
			img.parentNode.insertBefore(this._rootObj,img);
			
			if (img.complete) {
				this._Loader(parameters);
			} else {
				var self=this;
				// TODO: Remove jQuery dependency
				jQuery(this._img).bind("load", function()
				{
					self._Loader(parameters);
				});
			}
		}
	}
})();

Wilq32.PhotoEffect.prototype={
  _setupParameters : function (parameters){
		this._parameters = this._parameters || {};
    if (typeof this._angle !== "number") this._angle = 0 ;
    if (typeof parameters.angle==="number") this._angle = parameters.angle;
    this._parameters.animateTo = (typeof parameters.animateTo==="number") ? (parameters.animateTo) : (this._angle); 

    this._parameters.step = parameters.step || this._parameters.step || null;
		this._parameters.easing = parameters.easing || this._parameters.easing || function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b; }
		this._parameters.duration = parameters.duration || this._parameters.duration || 1000;
    this._parameters.callback = parameters.callback || this._parameters.callback || function(){};
    if (parameters.bind && parameters.bind != this._parameters.bind) this._BindEvents(parameters.bind); 
	},
	_handleRotation : function(parameters){
     this._setupParameters(parameters);
     if (this._angle==this._parameters.animateTo) {
       this._rotate(this._angle);
     }
     else { 
       this._animateStart();     
     }
	},

	_BindEvents:function(events){
		if (events && this._eventObj) 
		{
      // Unbinding previous Events
      if (this._parameters.bind){
        var oldEvents = this._parameters.bind;
        for (var a in oldEvents) if (oldEvents.hasOwnProperty(a)) 
            // TODO: Remove jQuery dependency
            jQuery(this._eventObj).unbind(a,oldEvents[a]);
      }

      this._parameters.bind = events;
			for (var a in events) if (events.hasOwnProperty(a)) 
				// TODO: Remove jQuery dependency
					jQuery(this._eventObj).bind(a,events[a]);
		}
	},

	_Loader:(function()
	{
		if (IE)
		return function(parameters)
		{
			var width=this._img.width;
			var height=this._img.height;
			this._img.parentNode.removeChild(this._img);
							
			this._vimage = this.createVMLNode('image');
			this._vimage.src=this._img.src;
			this._vimage.style.height=height+"px";
			this._vimage.style.width=width+"px";
			this._vimage.style.position="absolute"; // FIXES IE PROBLEM - its only rendered if its on absolute position!
			this._vimage.style.top = "0px";
			this._vimage.style.left = "0px";

			/* Group minifying a small 1px precision problem when rotating object */
			this._container = this.createVMLNode('group');
			this._container.style.width=width;
			this._container.style.height=height;
			this._container.style.position="absolute";
			this._container.setAttribute('coordsize',width-1+','+(height-1)); // This -1, -1 trying to fix ugly problem with small displacement on IE
			this._container.appendChild(this._vimage);
			
			this._rootObj.appendChild(this._container);
			this._rootObj.style.position="relative"; // FIXES IE PROBLEM
			this._rootObj.style.width=width+"px";
			this._rootObj.style.height=height+"px";
			this._rootObj.setAttribute('id',this._img.getAttribute('id'));
			this._rootObj.className=this._img.className;			
		  this._eventObj = this._rootObj;	
		  this._handleRotation(parameters);	
		}
		else
		return function (parameters)
		{
			this._rootObj.setAttribute('id',this._img.getAttribute('id'));
			this._rootObj.className=this._img.className;
			
			this._width=this._img.width;
			this._height=this._img.height;
			this._widthHalf=this._width/2; // used for optimisation
			this._heightHalf=this._height/2;// used for optimisation
			
			var _widthMax=Math.sqrt((this._height)*(this._height) + (this._width) * (this._width));

			this._widthAdd = _widthMax - this._width;
			this._heightAdd = _widthMax - this._height;	// widthMax because maxWidth=maxHeight
			this._widthAddHalf=this._widthAdd/2; // used for optimisation
			this._heightAddHalf=this._heightAdd/2;// used for optimisation
			
			this._img.parentNode.removeChild(this._img);	
			
			this._aspectW = ((parseInt(this._img.style.width,10)) || this._width)/this._img.width;
			this._aspectH = ((parseInt(this._img.style.height,10)) || this._height)/this._img.height;
			
			this._canvas=document.createElement('canvas');
			this._canvas.setAttribute('width',this._width);
			this._canvas.style.position="relative";
			this._canvas.style.left = -this._widthAddHalf + "px";
			this._canvas.style.top = -this._heightAddHalf + "px";
			this._canvas.Wilq32 = this._rootObj.Wilq32;
			
			this._rootObj.appendChild(this._canvas);
			this._rootObj.style.width=this._width+"px";
			this._rootObj.style.height=this._height+"px";
      this._eventObj = this._canvas;
			
			this._cnv=this._canvas.getContext('2d');
      this._handleRotation(parameters);
		}
	})(),

	_animateStart:function()
	{	
		if (this._timer) {
			clearTimeout(this._timer);
		}
		this._animateStartTime = +new Date;
		this._animateStartAngle = this._angle;
		this._animate();
	},
  _animate:function()
  {
     var actualTime = +new Date;
     var checkEnd = actualTime - this._animateStartTime > this._parameters.duration;

     // TODO: Bug for animatedGif for static rotation ? (to test)
     if (checkEnd && !this._parameters.animatedGif) 
     {
       clearTimeout(this._timer);
     }
     else 
     {
       if (this._canvas||this._vimage||this._img) {
         var angle = this._parameters.easing(0, actualTime - this._animateStartTime, this._animateStartAngle, this._parameters.animateTo - this._animateStartAngle, this._parameters.duration);
         this._rotate((~~(angle*10))/10);
       }
       if (this._parameters.step) {
        this._parameters.step(this._angle);
       }
       var self = this;
       this._timer = setTimeout(function()
           {
           self._animate.call(self);
           }, 10);
     }

     // To fix Bug that prevents using recursive function in callback I moved this function to back
     if (this._parameters.callback && checkEnd){
       this._angle = this._parameters.animateTo;
       this._rotate(this._angle);
       this._parameters.callback.call(this._rootObj);
     }
   },

	_rotate : (function()
	{
		var rad = Math.PI/180;
		if (IE)
		return function(angle)
		{
      this._angle = angle;
			this._container.style.rotation=(angle%360)+"deg";
		}
		else if (supportedCSS)
		return function(angle){
      this._angle = angle;
			this._img.style[supportedCSS]="rotate("+(angle%360)+"deg)";
		}
		else 
		return function(angle)
		{
      this._angle = angle;
			angle=(angle%360)* rad;
			// clear canvas	
			this._canvas.width = this._width+this._widthAdd;
			this._canvas.height = this._height+this._heightAdd;
						
			// REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..
			this._cnv.translate(this._widthAddHalf,this._heightAddHalf);	// at least center image on screen
			this._cnv.translate(this._widthHalf,this._heightHalf);			// we move image back to its orginal 
			this._cnv.rotate(angle);										// rotate image
			this._cnv.translate(-this._widthHalf,-this._heightHalf);		// move image to its center, so we can rotate around its center
			this._cnv.scale(this._aspectW,this._aspectH); // SCALE - if needed ;)
			this._cnv.drawImage(this._img, 0, 0);							// First - we draw image
		}

	})()
}

if (IE)
{
Wilq32.PhotoEffect.prototype.createVMLNode=(function(){
document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
		try {
			!document.namespaces.rvml && document.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
			return function (tagName) {
				return document.createElement('<rvml:' + tagName + ' class="rvml">');
			};
		} catch (e) {
			return function (tagName) {
				return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
			};
		}
})();
}
})(jQuery);

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun 测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JavaScript读取中文cookie时的乱码问题的解决方法
Oct 14 Javascript
javascript 多浏览器 事件大全
Mar 23 Javascript
JQuery datepicker 使用方法
May 20 Javascript
extjs render 用法介绍
Sep 11 Javascript
为Javascript中的String对象添加去除左右空格的方法(示例代码)
Nov 30 Javascript
jQuery插件jRumble实现网页元素抖动
Jun 05 Javascript
bootstrap-treeview自定义双击事件实现方法
Jan 09 Javascript
Angular使用ng-messages与PHP进行表单数据验证
Dec 28 Javascript
Bootstrap3 多个模态对话框无法显示的解决方案
Feb 23 Javascript
详解JS中的柯里化(currying)
Aug 17 Javascript
react学习笔记之state以及setState的使用
Dec 07 Javascript
Vue项目中使用flow做类型检测的方法
Mar 18 Javascript
JSONP 的原理、理解 与 实例分析
May 16 #Javascript
JavaScript随机数的组合问题案例分析
May 16 #Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
May 18 #Javascript
vue el-tree 默认展开第一个节点的实现代码
May 15 #Javascript
基于leaflet.js实现修改地图主题样式的流程分析
May 15 #Javascript
uni-app从安装到卸载的入门教程
May 15 #Javascript
Vue数据双向绑定原理实例解析
May 15 #Javascript
You might like
php使用MySQL保存session会话的方法
2015/06/18 PHP
thinkphp分页实现效果
2016/10/13 PHP
简单实用的PHP文本缓存类实例
2019/03/22 PHP
解决laravel资源加载路径设置的问题
2019/10/14 PHP
JavaScript中的object转换成number或string规则介绍
2014/12/31 Javascript
JavaScript使用ActiveXObject访问Access和SQL Server数据库
2015/04/02 Javascript
javascript实现checkbox全选的代码
2015/04/30 Javascript
jQuery CSS3相结合实现时钟插件
2016/01/08 Javascript
js仿百度切换皮肤功能(html+css)
2016/07/10 Javascript
浅谈MVC+EF easyui dataGrid 动态加载分页表格
2016/11/10 Javascript
angular仿支付宝密码框输入效果
2017/03/25 Javascript
MUI  Scroll插件的使用详解
2017/04/13 Javascript
es6学习笔记之Async函数基本教程
2017/05/11 Javascript
vue-amap根据地址回显地图并mark的操作
2020/11/03 Javascript
ant design pro中可控的筛选和排序实例
2020/11/17 Javascript
python比较2个xml内容的方法
2015/05/11 Python
详解Python编程中基本的数学计算使用
2016/02/04 Python
Python使用wxPython实现计算器
2018/01/30 Python
Python绘制并保存指定大小图像的方法
2019/01/10 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
Python机器学习算法库scikit-learn学习之决策树实现方法详解
2019/07/04 Python
python基于socket进行端口转发实现后门隐藏的示例
2019/07/25 Python
python并发编程多进程 互斥锁原理解析
2019/08/20 Python
Python 函数用法简单示例【定义、参数、返回值、函数嵌套】
2019/09/20 Python
Python实现桌面翻译工具【新手必学】
2020/02/12 Python
python连接mongodb数据库操作数据示例
2020/11/30 Python
详解CSS中iconfont的使用
2015/08/04 HTML / CSS
html5 postMessage前端跨域并前端监听的方法示例
2018/11/01 HTML / CSS
支票、地址标签、包装纸和慰问卡:Current Catalog
2018/01/30 全球购物
shell的种类有哪些
2015/04/15 面试题
单方离婚协议书范本(2014版)
2014/09/30 职场文书
小区的门卫岗位职责
2014/10/01 职场文书
三年级学生期末评语
2014/12/26 职场文书
校车安全管理责任书
2015/05/11 职场文书
单身证明范本
2015/06/15 职场文书
php中配置文件保存修改操作 如config.php文件的读取修改等操作
2021/05/12 PHP