We help IT Professionals succeed at work.

Add respin button to Wheel of Fortune spinner

AlHal2
AlHal2 asked
on
I have this code for a Wheel spinner using html, css and javascript.  At the moment, the only way I can get it to re-spin is to use the refresh button.  How can I add a button to re-spin the wheel?

I've tried adding a spin event and having the button call the spin event, but it fails even when the spin event just call init().
Here is the unminified javascript for SpinningWheelSource.js https://unpkg.com/konva@4.0.0/konva.js

<!DOCTYPE html>
<html>
  <head>
    <script src="SpinningWheelSource.js"></script>
    <meta charset="utf-8" />
    <title>Konva Wheel of Fortune Demo</title>
    
    <link rel="stylesheet" type="text/css" href="SpinningWheelStyle.css">
    
  </head>

  <body>
  <!--<button onclick="spin()">Spin</button>-->
  
    <div id="container"></div>
	
    <script>
	  //var myDiv=document.getElementById("container");
	  //var myParent=mydiv.parent;
      var width = window.innerWidth;
      var height = window.innerHeight;
      
      Konva.angleDeg = false;
      var angularVelocity = 6;
      var angularVelocities = [];
      var lastRotation = 0;
      var controlled = false;
      var numWedges = 10;  //not 25
      var angularFriction = 0.2;
      var target, activeWedge, stage, layer, wheel, pointer;
      var finished = false;
        var randy=Math.random();
		//alert("Random Number ="+randy)
		var Duration
		if (randy<0.1)
		    Duration =600;
		else if (randy<0.2)
		    Duration =650;
		else if (randy<0.3)
		    Duration =700;
		else if (randy<0.4)
		    Duration =750;
		else if (randy<0.5)
		    Duration =800;
		else if (randy<0.6)
		    Duration =850;
		else if (randy<0.7)
		    Duration =900;
		else if (randy<0.8)
		    Duration =950;
		else if (randy<0.9)
		    Duration =1000;
		else 
		    Duration =1050;	
      function getAverageAngularVelocity() {
        var total = 0;
        var len = angularVelocities.length;

        if (len === 0) {
          return 0;
        }

        for (var n = 0; n < len; n++) {
          total += angularVelocities[n];
        }

        return total / len;
      }
      function purifyColor(color) {
        var randIndex = Math.round(Math.random() * 3);
        color[randIndex] = 0;
        return color;
      }
      function getRandomColor() {
        var r = 100 + Math.round(Math.random() * 55);
        var g = 100 + Math.round(Math.random() * 55);
        var b = 100 + Math.round(Math.random() * 55);
        return purifyColor([r, g, b]);
      }

      function getRandomReward() {
        var mainDigit = Math.round(Math.random() * 9);
        return mainDigit + '\n0\n0';
      }
      function addWedge(n,wedgeText) {
        var s = getRandomColor();
        var reward = wedgeText;//getRandomReward();
        var r = s[0];
        var g = s[1];
        var b = s[2];
        var angle = (2 * Math.PI) / numWedges;

        //var endColor = 'rgb(' + r + ',' + g + ',' + b + ')';
		var endColor = 'rgb(' + 237 + ',' + 31 + ',' + 84+ ')';
        r += 100;
        g += 100;
        b += 100;

        //var startColor = 'rgb(' + r + ',' + g + ',' + b + ')';
		var startColor = 'rgb(' + 237 + ',' + 31 + ',' + 84 + ')';

        var wedge = new Konva.Group({
          rotation: (2 * n * Math.PI) / numWedges
        });

        var wedgeBackground = new Konva.Wedge({
          radius: 300,
          angle: angle,
          fillRadialGradientStartPoint: 0,
          fillRadialGradientStartRadius: 0,
          fillRadialGradientEndPoint: 0,
          fillRadialGradientEndRadius: 300,
          fillRadialGradientColorStops: [0, startColor, 1, endColor],
          fill: '#64e9f8',
          fillPriority: 'radial-gradient',
          stroke: '#ccc',
          strokeWidth: 2
        });

        wedge.add(wedgeBackground);

        var text = new Konva.Text({
          text: reward,
          fontFamily: 'Calibri',
          fontSize: 25,
          fill: 'white',
          align: 'center',
          stroke: 'yellow',
          strokeWidth: 1,
          rotation: (Math.PI + angle) / 2,
          x: 290,
          y: 25,
          listening: false
        });

        wedge.add(text);
        text.cache();

        wedge.startRotation = wedge.rotation();

        wheel.add(wedge);
      }
      function animate(frame) {
        // handle wheel spin
				
        var angularVelocityChange =
          (angularVelocity * frame.timeDiff * (1 - angularFriction)) / 1000;
        angularVelocity -= angularVelocityChange;

        // activate / deactivate wedges based on point intersection
        var shape = stage.getIntersection({
          x: stage.width() / 2,
          y: 100
        });

        if (controlled) {
          if (angularVelocities.length > 10) {
            angularVelocities.shift();
          }

          angularVelocities.push(
            ((wheel.rotation() - lastRotation) * 1000) / frame.timeDiff
          );
        } else {
          var diff = (frame.timeDiff * angularVelocity) / Duration;
          if (diff > 0.0001) {
            wheel.rotate(diff);
          } else if (!finished && !controlled) {
            if (shape) {
              var text = shape
                .getParent()
                .findOne('Text')
                .text();
              var price = text.split('\n').join('');
			  var message="splodge";
			  switch (price)
			  {
				case "Research":
					message="Research me";
					break;	
				case "Retention":
					message="Retain me";
					break;
				case "Results":
					message="The results";
					break;
				default:
				    message="Break";
			  }
              //alert('Your price is ' + price+".  Duration = "+Duration+".  Random Number ="+randy );
			  alert (message);
            }
            finished = true;
          }
        }
        lastRotation = wheel.rotation();

        if (shape) {
          if (shape && (!activeWedge || shape._id !== activeWedge._id)) {
            pointer.y(20);
            
            new Konva.Tween({
              node: pointer,
              duration: 0.3,
              y: 30,
              easing: Konva.Easings.ElasticEaseOut
            }).play();

            if (activeWedge) {
              activeWedge.fillPriority('radial-gradient');
            }
            shape.fillPriority('fill');
            activeWedge = shape;
          }
        }
      }
      function init() {
	  //var myDiv=document.getElementById("container");
	  //var myParent=myDiv.parent;
      //var width = window.innerWidth;
      //var height = window.innerHeight;
      //width = myParent.innerWidth;
      //height = myParent.innerHeight;
        stage = new Konva.Stage({
          container: 'container',
          width: width,
          height: height
        });
        layer = new Konva.Layer();
        wheel = new Konva.Group({
          x: stage.width() / 2,
          y: 350
        });

        //for (var n = 0; n < numWedges; n++) {
        //  addWedge(n);
        //}
		addWedge(0,"Retention");
		addWedge(1,"Results");
		addWedge(2,"Retention");
		addWedge(3,"Recruit");
		addWedge(4,"Research");
		addWedge(5,"Recognition");
		addWedge(6,"Results");
		addWedge(7,"Recruitment");
		addWedge(8,"Recognition");
		addWedge(9,"Research");
        pointer = new Konva.Wedge({
          fillRadialGradientStartPoint: 0,
          fillRadialGradientStartRadius: 0,
          fillRadialGradientEndPoint: 0,
          fillRadialGradientEndRadius: 30,
          fillRadialGradientColorStops: [0, 'white', 1, 'red'],
          stroke: 'white',
          strokeWidth: 2,
          lineJoin: 'round',
          angle: 1,
          radius: 30,
          x: stage.width() / 2,
          y: 33,
          rotation: -90,
          shadowColor: 'black',
          shadowOffsetX: 3,
          shadowOffsetY: 3,
          shadowBlur: 2,
          shadowOpacity: 0.5
        });

        // add components to the stage
        layer.add(wheel);
        layer.add(pointer);
        stage.add(layer);

        // bind events
        wheel.on('mousedown touchstart', function(evt) {
          angularVelocity = 0;
          controlled = true;
          target = evt.target;
          finished = false;
        });
        // add listeners to container
        stage.addEventListener(
          'mouseup touchend',
          function() {
            controlled = false;
            angularVelocity = getAverageAngularVelocity() * 5;

            if (angularVelocity > 20) {
              angularVelocity = 20;
            } else if (angularVelocity < -20) {
              angularVelocity = -20;
            }

            angularVelocities = [];
          },
          false
        );

        stage.addEventListener(
          'mousemove touchmove',
          function(evt) {
            var mousePos = stage.getPointerPosition();
            if (controlled && mousePos && target) {
              var x = mousePos.x - wheel.getX();
              var y = mousePos.y - wheel.getY();
              var atan = Math.atan(y / x);
              var rotation = x >= 0 ? atan : atan + Math.PI;
              var targetGroup = target.getParent();

              wheel.rotation(
                rotation - targetGroup.startRotation - target.angle() / 2
              );
            }
          },
          false
        );

        var anim = new Konva.Animation(animate, layer);

        // wait one second and then spin the wheel
        setTimeout(function() {
          anim.start();
        }, 1000);
      }
function closeAlertBox(){
    alertBox = document.getElementById("alertBox");
    alertClose = document.getElementById("alertClose");
    alertBox.style.visibility = "hidden";
    alertClose.style.visibility = "hidden";
}
window.alert = function(msg){
    var id = "alertBox", alertBox, closeId = "alertClose", alertClose;
    alertBox = document.createElement("div");
    document.body.appendChild(alertBox);
    alertBox.id = id;
    alertBox.innerHTML = msg;
    alertClose = document.createElement("div");
    alertClose.id = closeId;
    alertClose.innerHTML = "x";
    alertBox.appendChild(alertClose);
    alertBox.style.visibility = "visible";
    alertClose.style.visibility = "visible";
    alertClose.onclick = closeAlertBox;
};
      init();

	  
    </script>
	
  </body>

</html>

Open in new window


      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
        background-color: #f0f0f0;
      }
	    #alertBox{
    position:absolute;
    top:200px;
    left:200px;
    border:solid 3px black;
    background-color: #528CE0;
    padding: 80px;
    visibility: hidden;
}
#alertClose{
    position: absolute;
    right:0;
    top: 0;
    background-color: black;
    border: solid 1px white;
    color: white;
    width: 1em;
    text-align: center; 
    cursor: pointer;
}

Open in new window

Comment
Watch Question

Hi,

You can compare your code with their demo
https://konvajs.org/docs/sandbox/Wheel_of_Fortune.html

check that part
stage.addEventListener(
          'mousemove touchmove',
          function(evt) {
            var mousePos = stage.getPointerPosition();
            if (controlled && mousePos && target) {
              var x = mousePos.x - wheel.getX();
              var y = mousePos.y - wheel.getY();
              var atan = Math.atan(y / x);
              var rotation = x >= 0 ? atan : atan + Math.PI;
              var targetGroup = target.getParent();

              wheel.rotation(
                rotation - targetGroup.startRotation - target.angle() / 2
              );
            }
          },
          false
        );

Open in new window


You can set a jsfiddle so we can help you to fix you code

Author

Commented:
Is it a matter of adding an event listener for the button press?
How do I set a jsfiddle?

Author

Commented:
Do I need to add an event listener for a button click or just add a button with a link to a function eg
<button onclick="spin()">Spin</button>
function spin()

{

           pointer.y(20);
            
            new Konva.Tween({
              node: pointer,
              duration: 0.3,
              y: 30,
              easing: Konva.Easings.ElasticEaseOut
            }).play();




        var anim = new Konva.Animation(animate, layer);

 
          anim.start();

}

Open in new window

Commented:
This seems to work

<!DOCTYPE html>
<html>
  <head>
    <script src="SpinningWheelSourceUnMinified.js"></script>
    <meta charset="utf-8" />
    <title>Konva Wheel of Fortune Demo</title>
    
    <link rel="stylesheet" type="text/css" href="SpinningWheelStyle.css">
    
  </head>

  <body>
 
  <button onclick="spin()" class="css3Button">Spin</button>
  <div class="circle-txt">Foo Bar!</div>
    <div id="container"></div>
	 
    <script>
	  //var myDiv=document.getElementById("container");
	  //var myParent=mydiv.parent;
	  var manual=false;
      var width = window.innerWidth;
      var height = window.innerHeight;
      var anim;
	  var timer;
	  var firstRun=true;
      Konva.angleDeg = false;
      var angularVelocity = 6;
      var angularVelocities = [];
      var lastRotation = 0;
      var controlled = false;
      var numWedges = 10;  //not 25
      var angularFriction = 0.2;
      var target, activeWedge, stage, layer, wheel, pointer;
      var finished = false;
        var randy=Math.random();
		//alert("Random Number ="+randy)
		var Duration
		if (randy<0.1)
		    Duration =600;
		else if (randy<0.2)
		    Duration =650;
		else if (randy<0.3)
		    Duration =700;
		else if (randy<0.4)
		    Duration =750;
		else if (randy<0.5)
		    Duration =800;
		else if (randy<0.6)
		    Duration =850;
		else if (randy<0.7)
		    Duration =900;
		else if (randy<0.8)
		    Duration =950;
		else if (randy<0.9)
		    Duration =1000;
		else 
		    Duration =1050;	
 
      function addWedge(n,wedgeText) {
   
        var reward = wedgeText;//getRandomReward();
  
        var angle = (2 * Math.PI) / numWedges;

		
					  switch (wedgeText)
			  {
				case "Research":
					var endColor = 'rgb(' + 255 + ',' + 135 + ',' + 60+ ')';
					var startColor = 'rgb(' + 255 + ',' + 135 + ',' + 60 + ')';
					break;	
                case "Recognition":
					var endColor = 'rgb(' + 255 + ',' + 190 + ',' + 50+ ')';
					var startColor = 'rgb(' + 255 + ',' + 190 + ',' + 50 + ')';
					break;	
				case "Retention":
					var endColor = 'rgb(' + 25 + ',' + 215 + ',' + 155+ ')';
					var startColor = 'rgb(' + 25 + ',' + 215 + ',' + 155 + ')';
					break;
				case "Recruitment":
					var endColor = 'rgb(' + 00 + ',' + 160 + ',' + 110+ ')';
					var startColor = 'rgb(' + 00 + ',' + 160+ ',' + 110 + ')';
					break;
				case "Results":
					var endColor = 'rgb(' + 80 + ',' + 10 + ',' + 180+ ')';
					var startColor = 'rgb(' + 80 + ',' + 10+ ',' + 180 + ')';
					break;
				default:
				    message="Break";
			  }


        var wedge = new Konva.Group({
          rotation: (2 * n * Math.PI) / numWedges
        });

        var wedgeBackground = new Konva.Wedge({
          radius: 300,
          angle: angle,
          fillRadialGradientStartPoint: 0,
          fillRadialGradientStartRadius: 0,
          fillRadialGradientEndPoint: 0,
          fillRadialGradientEndRadius: 300,
          fillRadialGradientColorStops: [0, startColor, 1, endColor],
          fill: '#64e9f8',
          fillPriority: 'radial-gradient',
          stroke: '#ccc',
          strokeWidth: 2
        });

        wedge.add(wedgeBackground);

        var text = new Konva.Text({
          text: reward,
          fontFamily: 'Calibri',
          fontSize: 25,
          fill: 'white',
          align: 'center',
          stroke: 'yellow',
          strokeWidth: 1,
          rotation: (Math.PI + angle) / 2,
          x: 290,
          y: 25,
          listening: false
        });

        wedge.add(text);
        text.cache();

        wedge.startRotation = wedge.rotation();

        wheel.add(wedge);
      }
      function animate(frame) {
        // handle wheel spin
	    //console.log(lastRotation);
		if (manual==true)
		{
		   manual=false;
		   frame.timeDiff=1;
		   angularVelocity=Math.random()*10;
		   Duration=500;
		}
		if (firstRun==true)
		{
		   
		   firstRun=false;
		   //frame.timeDiff=1;
		   console.log("frame.timeDiff" + frame.timeDiff);
		   console.log("angularVelocity" + angularVelocity);
		}
        var angularVelocityChange =
          (angularVelocity * frame.timeDiff * (1 - angularFriction)) / 1000;
        angularVelocity -= angularVelocityChange;
        // activate / deactivate wedges based on point intersection
        var shape = stage.getIntersection({
          x: stage.width() / 2,
          y: 100
        });

        if (controlled) {
		  console.log("controlled");
          if (angularVelocities.length > 10) {
            angularVelocities.shift();
          }

          angularVelocities.push(
            ((wheel.rotation() - lastRotation) * 1000) / frame.timeDiff
          );
        } else {
		  
          var diff = (frame.timeDiff * angularVelocity) / Duration;
		  //console.log(diff);
          if (diff > 0.0001) {
		    //console.log ("rotating");
            wheel.rotate(diff);
          } else if (!finished && !controlled) {
		    //console.log ("rotating timeDiff: " + frame.timeDiff);
			//console.log ("angular velocity: " + angularVelocity);
			//console.log ("Duration: " + Duration );
			//console.log ("Diff: " + diff );
            if (shape) {
              var text = shape
                .getParent()
                .findOne('Text')
                .text();
              var price = text.split('\n').join('');
			  clearTimeout(timer);
			  var message="splodge";
			  switch (price)
			  {
				case "Research":
					message="Research me";
					break;	
				case "Retention":
					message="Retain me";
					break;
				case "Results":
					message="The results";
					break;
				default:
				    message="Break";
			  }
              //alert('Your price is ' + price+".  Duration = "+Duration+".  Random Number ="+randy );
			  alert (message);
            }
            finished = true;
          }
        }
        lastRotation = wheel.rotation();

        if (shape) {
          if (shape && (!activeWedge || shape._id !== activeWedge._id)) {
            pointer.y(20);
            
            new Konva.Tween({
              node: pointer,
              duration: 0.3,
			  //rotationDeg: 360,
              y: 40,
              easing: Konva.Easings.ElasticEaseOut
            }).play();

            if (activeWedge) {
              activeWedge.fillPriority('radial-gradient');
            }
            shape.fillPriority('fill');
            activeWedge = shape;
          }
        }
      }
      function init() {
	
        stage = new Konva.Stage({
          container: 'container',
          width: width,
          height: height
        });
        layer = new Konva.Layer();
        wheel = new Konva.Group({
          x: stage.width() / 2,
          y: 350
        });

        //for (var n = 0; n < numWedges; n++) {
        //  addWedge(n);
        //}
		addWedge(0,"Retention");
		addWedge(1,"Results");
		addWedge(2,"Recruitment");
		addWedge(3,"Research");
		addWedge(4,"Recognition");
	    addWedge(5,"Retention");
		addWedge(6,"Results");
		addWedge(7,"Recruitment");
		addWedge(8,"Research");
		addWedge(9,"Recognition")
        pointer = new Konva.Wedge({
          fillRadialGradientStartPoint: 0,
          fillRadialGradientStartRadius: 0,
          fillRadialGradientEndPoint: 0,
          fillRadialGradientEndRadius: 30,
          fillRadialGradientColorStops: [0, 'white', 1, 'red'],
          stroke: 'white',
          strokeWidth: 2,
          lineJoin: 'round',
          angle: 1,
          radius: 30,
          x: stage.width() / 2,
          y: 33,
          rotation: -90,
          shadowColor: 'black',
          shadowOffsetX: 3,
          shadowOffsetY: 3,
          shadowBlur: 2,
          shadowOpacity: 0.5
        });

        // add components to the stage
        layer.add(wheel);
        layer.add(pointer);
        stage.add(layer);


        anim = new Konva.Animation(animate, layer);
        // wait one second and then spin the wheel
        timer=setTimeout(function() {
          anim.start();
        }, 1000);
      }

      init();
function spin()

{
manual=true;
finished=false;
controlled = false
          

lastRotation=0;
   
		 layer = new Konva.Layer();
		 anim = new Konva.Animation(animate, layer);
		 
        timer=setTimeout(function() {
          anim.start();
        }, 1000);
}
function closeAlertBox(){
    console.log ("Bye2a");
    alertBox = document.getElementById("alertBox");
    alertClose = document.getElementById("alertClose");
    alertBox.parentNode.removeChild(alertBox);
    alertClose.parentNode.removeChild(alertClose)
	//alertBox.style.visibility = "hidden";
    //alertClose.style.visibility = "hidden";
	console.log ("Bye2b");
}
window.alert = function(msg){
    console.log ("Bye1a");
    var id = "alertBox", alertBox, closeId = "alertClose", alertClose;
    alertBox = document.createElement("div");
    document.body.appendChild(alertBox);
    alertBox.id = id;
    alertBox.innerHTML = msg;
    alertClose = document.createElement("div");
    alertClose.id = closeId;
    document.body.appendChild(alertClose);
    alertClose.innerHTML = "x";
    alertBox.appendChild(alertClose);
    alertBox.style.visibility = "visible";
    alertClose.style.visibility = "visible";
    alertClose.onclick = closeAlertBox;
	console.log ("Bye1b")
};
	  
    </script>
	
  </body>

</html>

Open in new window