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 function、指针及内置对象
Feb 19 Javascript
cnblogs TagCloud基于jquery的实现代码
Jun 11 Javascript
jQuery实现网页顶部固定导航效果代码
Dec 24 Javascript
使用jQuery UI库开发Web界面的简单入门指引
Apr 22 Javascript
Bootstrap Table使用方法解析
Oct 19 Javascript
Vue 2.x教程之基础API
Mar 06 Javascript
jQuery访问浏览器本地存储cookie、localStorage和sessionStorage的基本用法
Oct 20 jQuery
Angular2学习笔记之数据绑定的示例代码
Jan 03 Javascript
vue实现输入框自动跳转功能
May 20 Javascript
15个简单的JS编码标准让你的代码更整洁(小结)
Jul 16 Javascript
mapboxgl实现带箭头轨迹线的代码
Jan 04 Javascript
详解vue中v-for的key唯一性
May 15 Vue.js
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乱码,用set names XXX解决的原理分享
2011/12/29 PHP
PHP包含文件函数include、include_once、require、require_once区别总结
2014/04/05 PHP
nginx下安装php7+php5
2016/07/31 PHP
ThinkPHP框架实现导出excel数据的方法示例【基于PHPExcel】
2018/05/12 PHP
如何在PHP环境中使用ProtoBuf数据格式
2020/06/19 PHP
javascript中删除指定数组中指定的元素的代码
2011/02/12 Javascript
JS对象与JSON格式数据相互转换
2012/02/20 Javascript
JS解决ie6下png透明的方法实例
2013/08/02 Javascript
JavaScript实现网站访问次数统计代码
2015/08/12 Javascript
jquery马赛克拼接翻转效果代码分享
2015/08/24 Javascript
bootstrap配合Masonry插件实现瀑布式布局
2017/01/18 Javascript
bootstrap fileinput 插件使用项目总结(经验)
2017/02/22 Javascript
JS鼠标滚动分页效果示例
2017/07/05 Javascript
微信JSAPI Ticket接口签名详解
2020/06/28 Javascript
微信小程序左右滚动公告栏效果代码实例
2019/09/16 Javascript
layui禁用侧边导航栏点击事件的解决方法
2019/09/25 Javascript
微信小程序8种数据通信的方式小结
2020/02/03 Javascript
Bootstrap实现前端登录页面带验证码功能完整示例
2020/03/26 Javascript
两个命令把 Vim 打造成 Python IDE的方法
2016/03/20 Python
python socket多线程通讯实例分析(聊天室)
2016/04/06 Python
安装python时MySQLdb报错的问题描述及解决方法
2018/03/20 Python
Python发送邮件测试报告操作实例详解
2018/12/08 Python
python 实现一次性在文件中写入多行的方法
2019/01/28 Python
python 实现selenium断言和验证的方法
2019/02/13 Python
AmazeUI的JS表单验证框架实战示例分享
2020/08/21 HTML / CSS
GLAMGLOW格莱魅美国官网:美国知名的面膜品牌
2016/12/31 全球购物
英国最大的在线奢侈手表零售商:Jura Watches
2018/01/29 全球购物
英国厨房与餐具用品为主的设计品牌:Joseph Joseph
2018/04/26 全球购物
电脑租赁公司创业计划书
2014/01/08 职场文书
幼儿园教师培训制度
2014/01/16 职场文书
用人单位聘用意向书
2015/05/11 职场文书
2015年除四害工作总结
2015/07/23 职场文书
涨工资申请书应该怎么写?
2019/07/08 职场文书
浅谈JS和Nodejs中的事件驱动
2021/05/05 NodeJs
如何利用Python实现一个论文降重工具
2021/07/09 Python
Golang流模式之grpc的四种数据流
2022/04/13 Golang