我在尝试使用画布实现“奖杯轮”时遇到了麻烦。我使用的是类似于StackOverflow上浮动的画布“轮盘赌轮” http://jsfiddle.net/wYhvB/4/的东西。我的难题是,当您单击旋转时,在后台我进行了API调用,该API返回了应实际选择奖品的ID,界面不过是吸引人的东西。我将所有奖金说明推送到第一个数组中,如何将ID添加到每个弧中并停止在特定的弧上,而不是在特定的随机时间停止?即如果API返回“汽车”,我希望该轮子旋转几次并停在汽车上。

    var colors = ["##eaeaea", "##cccccc", "##eaeaea", "##cccccc",
                  "##eaeaea", "##cccccc", "##eaeaea", "##cccccc"];
    // NEED to pre load this data prior
    var prize_descriptions = ["car","house","etc..."]; // These are injected on an init call from an api
    var current_user_status = {};

    var startAngle = 0;
    var arc = Math.PI / 4;
    var spinTimeout = null;

    var spinArcStart = 10;
    var spinTime = 0;
    var spinTimeTotal = 0;

    var current_user_status = null;
    var spin_results = null;

    var ctx;

    function drawSpinnerWheel() {
      var canvas = document.getElementById("canvas");
      if (canvas.getContext) {
        var outsideRadius = 200;
        var textRadius = 160;
        var insideRadius = 125;

        ctx = canvas.getContext("2d");
        ctx.clearRect(0,0,500,500);


        ctx.strokeStyle = "black";
        ctx.lineWidth = 2;

        ctx.font = 'bold 12px Helvetica, Arial';

        for(var i = 0; i < 8; i++) {
          var angle = startAngle + i * arc;
          ctx.fillStyle = colors[i];

          ctx.beginPath();
          ctx.arc(250, 250, outsideRadius, angle, angle + arc, false);
          ctx.arc(250, 250, insideRadius, angle + arc, angle, true);
          ctx.stroke();
          ctx.fill();

          ctx.save();
          ctx.shadowOffsetX = -1;
          ctx.shadowOffsetY = -1;
          ctx.shadowBlur    = 0;
          ctx.shadowColor   = "rgb(220,220,220)";
          ctx.fillStyle = "black";
          ctx.translate(250 + Math.cos(angle + arc / 2) * textRadius,
                        250 + Math.sin(angle + arc / 2) * textRadius);
          ctx.rotate(angle + arc / 2 + Math.PI / 2);
          var text = prize_descriptions[i];
          if (text == undefined)
            text = "Not this time! "+i;
          ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
          ctx.restore();
        }

        //Arrow
        ctx.fillStyle = "black";
        ctx.beginPath();
        ctx.moveTo(250 - 4, 250 - (outsideRadius + 5));
        ctx.lineTo(250 + 4, 250 - (outsideRadius + 5));
        ctx.lineTo(250 + 4, 250 - (outsideRadius - 5));
        ctx.lineTo(250 + 9, 250 - (outsideRadius - 5));
        ctx.lineTo(250 + 0, 250 - (outsideRadius - 13));
        ctx.lineTo(250 - 9, 250 - (outsideRadius - 5));
        ctx.lineTo(250 - 4, 250 - (outsideRadius - 5));
        ctx.lineTo(250 - 4, 250 - (outsideRadius + 5));
        ctx.fill();
      }
    }

    function spin() {
      spinAngleStart = Math.random() * 10 + 10;
      spinTime = 0;
      spinTimeTotal = Math.random() * 3 + 4 * 1000;
      rotateWheel();
    }

    function rotateWheel() {
      spinTime += 30;
      if(spinTime >= spinTimeTotal) {
        stopRotateWheel();
        return;
      }
      var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
      startAngle += (spinAngle * Math.PI / 180);
      drawSpinnerWheel();
      spinTimeout = setTimeout('rotateWheel()', 30);
    }

    function stopRotateWheel() {
      clearTimeout(spinTimeout);
      var degrees = startAngle * 180 / Math.PI + 90;
      var arcd = arc * 180 / Math.PI;
      var index = Math.floor((360 - degrees % 360) / arcd);
      ctx.save();
      ctx.font = 'bold 30px Helvetica, Arial';
      var text = prize_descriptions[index];
      ctx.fillText(text, 250 - ctx.measureText(text).width / 2, 250 + 10);
      ctx.restore();
    }

    function easeOut(t, b, c, d) {
      var ts = (t/=d)*t;
      var tc = ts*t;
      return b+c*(tc + -3*ts + 3*t);
    }


drawSpinnerWheel();

$("#spin").bind('click', function(e) {
  e.preventDefault();
  spin();
});​

最佳答案

我在创建HTML5帆布制胜轮方面有一些经验,我解决了使轮停在服务器端流程确定的特定奖品上的问题的方法是,定义与奖品对应的奖品阵列轮,以度为单位指定每个奖品的开始和结束角度,然后在旋转轮之前,将targetAngle设置为相关奖品的开始和结束角度之间的随机值,再加上360度的倍数,这样车轮旋转几次,然后减速至预定奖赏的停止位置。

例如,如果转轮有4个奖项,则奖项数组为...

var prizes = new Array();
prizes[0] = {"name" : "Prize 1", "startAngle" : 0,   "endAngle" : 89};
prizes[1] = {"name" : "Prize 2", "startAngle" : 90,  "endAngle" : 179};
prizes[2] = {"name" : "Prize 3", "startAngle" : 180, "endAngle" : 269};
prizes[3] = {"name" : "Prize 4", "startAngle" : 270, "endAngle" : 359};


设置targetAngle的代码类似于...

targetAngle = Math.floor(prizes[determinedPrize]['startAngle'] + (Math.random() * (prizes[determinedPrize]['endAngle'] - prizes[determinedPrize]['startAngle'])));
targetAngle += (360 * 18);


然后,车轮的旋转功能会循环直到车轮的当前角度等于目标角度。

http://www.dougtesting.net中提供了我的奖金轮和完整注释的源代码的工作示例。在线示例中未启用该预定功能,但是一旦下载,就可以在源代码(winwheel.js)中轻松打开该预定功能。

关于javascript - HTML5 Canvas和JavaScript奖轮,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13129616/

10-09 18:12
查看更多