salad_bar_breath
salad_bar_breath

Reputation: 281

HTML5 canvas not doing what I want with jquery hover() method

So basically I am trying to make a circle that gradually fills in the "border" with a different shade as the user hovers over it.

It works pretty well, but I want it to go away when the user isn't hovering and "restart" at the top of the circle when the user hovers back over it. Instead it continues the while loop regardless of the parameter.

I've tried a couple things including adding a boolean variable called "stop", anding it to the while loop parameters, which does nothing.

All I have on the html is a slightly styled canvas which as you can see by my script has an ID of "wheel1". Here is my JavaScript:

var c = document.getElementById("wheel1");
var ctx = c.getContext("2d");
var y = 0;
var stop = false;

var topCircle = function() {
  ctx.beginPath();
  ctx.fillStyle = "#AAAAAA";
  ctx.arc(50, 50, 40, 0, 2 * Math.PI);
  ctx.fill();
  ctx.closePath();
}

var origCircle = function() {
  ctx.beginPath();
  ctx.fillStyle = "#CCCCCC";
  ctx.arc(50, 50, 50, 0, 2 * Math.PI);
  ctx.fill();
  ctx.closePath();
  topCircle();
}

function hoverEffect(x) {
  setTimeout(function() { 
    ctx.beginPath();
    ctx.fillStyle = "#000000";
    ctx.moveTo(50, 50);
    ctx.arc(50, 50, 50, (1.5 + x/1000) * Math.PI, (1.555 + x/1000) * Math.PI);
    ctx.lineTo(50, 50);
    ctx.fill();
    ctx.closePath();
    topCircle();
  }, (x/2));
}

origCircle();
$('#wheel1').hover(function() {
  stop = false;
  do {
    hoverEffect(y);
    y += 50;
  } 
  while (y <= 2000 && stop == false);
}, function() {
  stop = true;
  y = 0;
  origCircle();
});

EDIT: Jquery 1.11.3 api is in head and here is the FIDDLE

Upvotes: 2

Views: 296

Answers (2)

markE
markE

Reputation: 105035

On hover:

  • Set an isHovering flag to true.
  • Reset a percent-of-arc-to-draw variable (pct) to 0%
  • Start an animation loop that increases pct from 0% to 100% over time and redraws the arc based on that pct.

On blur:

  • Set an isHovering flag to false
  • Set a percent-of-arc-to-draw variable (pct) to 100% (100% causes any animation to stop).

Then draw the arc:

  • Clear the canvas,
  • Fill the full arc with gray,
  • Stroke the full arc with lightgray,
  • If the isHovering flag is set, stroke the arc in black based on percent-of-arc-to-draw.

Here's example code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
ctx.lineWidth=12;
ctx.fillStyle='gray';

var PI=Math.PI;
var PI2=PI*2;
var cx=cw/2;
var cy=ch/2;
var radius=Math.min(cx,cy)-ctx.lineWidth/2;
var pct=0;
var pctIncrement=100/60;
var startAngle=-PI/2;
var hoverStyle='black';
var blurStyle='lightgray';
var isHovering=false;

draw()

function draw(){

  ctx.clearRect(0,0,canvas.width,canvas.height);

  // always draw blur arc
  ctx.beginPath();
  ctx.arc(cx,cy,radius,startAngle,startAngle+PI2);
  ctx.strokeStyle=blurStyle;
  ctx.fill();
  ctx.stroke();

  // draw hover arc when hovering
  if(isHovering){
    ctx.beginPath();
    ctx.arc(cx,cy,radius,startAngle,startAngle+PI2*pct/100);
    ctx.strokeStyle=hoverStyle;
    ctx.stroke();
  }
}

//
function animate(time){

  draw();

  pct+=pctIncrement;
  if(pct>100){pct=100;}

  if(isHovering && pct<=100){
    requestAnimationFrame(animate);
  }

}

$("#canvas").hover(
  function(){
    isHovering=true;
    pct=0;
    requestAnimationFrame(animate);
  },
  function(){
    isHovering=false;
    pct=100;
    draw();
  }
);
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Hover over the red canvas.</h4>
<canvas id="canvas" width=100 height=100></canvas>

Upvotes: 1

DinoMyte
DinoMyte

Reputation: 8868

Your problem is very tricky since you are using a timeout function. Due to this even when you hover off the canvas, hover event is executed and draws the black inner outer circle. One possible way to fix it is to initiate another timeout function which resets the state of the canvas.

 function reset() {
        setTimeout(function () {
            origCircle();
        }, 900);
    }

$('#wheel1').hover(
function(){
        stop = false;
     do {
        hoverEffect(y);
        y += 50;
    } 
    while (y <= 2000 && stop == false);
}, function(){
        stop = true;
        y = 0;
        origCircle();
    reset(); 
});

Updated fiddle : http://jsfiddle.net/dab65vzb/2/

Upvotes: 1

Related Questions