欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js抽奖转盘实现方法分析

程序员文章站 2022-03-07 13:44:00
本文实例讲述了js抽奖转盘实现方法。分享给大家供大家参考,具体如下:html 这里.left 固定了圆的宽度和高度,还有canvas也设置了固定宽高 绘制圆心的坐标也就出来了 (203,203)抽奖转...

本文实例讲述了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.jb51.net/code/htmljsrun 测试上述代码运行效果。