0

I have a bunch of colored areas and when I enter any of them, I want the text to fade out. When I'm leaving the colored area, I want the text to fade in. This far, it's easy. The problem arises when I leave an area and enter an adjacent one.

If I only toggleIn() and toggleOut(), it works, but the fading effect makes the text appear and then re-disappear again, which looks stupid.

The extra problem is that the areas can't be placed in a single holder because they are not rectangularly positioned (and, in fact, it's parts of a SVG based pie chart drawn with D3).

I've been testing an external variable to keep track in the entry is made from outside of all areas or from outside of this but inside of another, adjacent area). Didn't quite managed to work it out.

How to make it happen in this fiddle?

$(".dragon")
  .on("mouseenter", function(target) {
    $("#indicator").fadeOut();
  })
  .on("mouseleave", function(target) {
    $("#indicator").fadeIn();
  });
Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438

3 Answers3

1

When you go from a dragon area to another the first one's mouseleave() event will rise and the second one's mouseenter() event will rise. That's why it shows the text and hide it again. This is what i resolved by updating your jsfiddle.

As I inderstood from your question when the user enters to the ".dragon" area you want to hide the text. And when passing from a ".dragon" element to another instead of just showing and hiding the text you want the text to just stay hidden.

A solution i can think of is in the document ready function you can create two global variables for bottom-right corner of the ".dragon" elements. Let's say the variables are (according to the size of your Jsfiddle);

var globalX = 200;
var globalY = 400;

And you put your fade functionality into mousemove() event.

$('body').mousemove(function(event){
    if(event.pageY > 400 || event.pageX > 200){
        $("#indicator").fadeIn();
    }
    else{
        $("#indicator").fadeOut();
    }
});
Cengiz Araz
  • 680
  • 9
  • 17
  • Sadly, that's not going to cut it. I'd like to redirect your attention to the third paragraphs in OP. My area is actually a bunch of arcs that constitute a pie chart sectors. No rectangle at all... – Konrad Viltersten Jun 28 '16 at 18:36
  • @KonradViltersten if the pie charts represent a circle, you can check if the mouse is in the circle by calculating the distance of the mouse pointer from the center of the circle. If the distance is smaller then the radius of that circle that means it's in the element. You can check the following task. http://stackoverflow.com/questions/16792841/detect-if-user-clicks-inside-a-circle – Cengiz Araz Jun 28 '16 at 19:16
  • @KonradViltersten have you found a solution? – Cengiz Araz Jul 01 '16 at 18:57
  • Yes and no. I've got a suggestion above with *queue* parameter. It follows the approach I need with only the slight issue that if we exit to quickly, the fade in doesn't kick in. (BTW, in my case, there will also be labels and other stuff making the chart irregularly shaped, which prevents me from computations based on the form - rectangle, circle etc. I might have forgotten to mention that, sorry.) – Konrad Viltersten Jul 04 '16 at 08:45
  • @KonradViltersten that's ok man. I learned something thanks to you as well :) – Cengiz Araz Jul 05 '16 at 15:57
1

The fadeIn() and fadeOut() functions can take an options parameter. One of the options is queue. If you set that to false on the fadeOut(), then it will interrupt the fade in animation. You won't see the full opacity text when you move between hover targets.

$(".dragon")
  .on("mouseenter", function(target) {
    $("#indicator").fadeOut({queue: false});
  })
  .on("mouseleave", function(target) {
    $("#indicator").fadeIn();
  });
div {
  width: 200px;
  height: 200px;
  text-align: center;
}

.uno {
  background-color: blue;
}

.duo {
  background-color: yellow;
}

#indicator {
  color: red;
  font-family: Tahoma;
  font-size: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dragon uno"></div>
<div class="dragon duo"></div>

<div id="indicator"><hr>Enter the dragon!</div>

Update

There seems to be an issue with jQuery's fadeIn() and fadeOut() functions where they get confused by mouseenter and mouseleave events that are quick in succession. Switching to using the animate() function directly seems to fix the problem though.

$(".dragon")
  .on("mouseenter", function(target) {
    $("#indicator").animate({opacity: 0}, {queue: false});
  })
  .on("mouseleave", function(target) {
    $("#indicator").animate({opacity: 1});
  });

$(".dragon")
  .on("mouseenter", function(target) {
    $("#indicator").animate({opacity: 0}, {queue: false});
  })
  .on("mouseleave", function(target) {
    $("#indicator").animate({opacity: 1});
  });
div {
  width: 200px;
  height: 200px;
  text-align: center;
}

.uno {
  background-color: blue;
}

.duo {
  background-color: yellow;
}

#indicator {
  color: red;
  font-family: Tahoma;
  font-size: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dragon uno"></div>
<div class="dragon duo"></div>

<div id="indicator"><hr>Enter the dragon!</div>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Yes, this is the behavior I'm aiming at. Awesome suggestions, I may add. There's only a tiny issue with the behavior **if moving too quickly**. Try to enter the area (the text vanishes as supposed to) but then mouse out immediately (probably, the exit needs to occur before the fade duration is delivered). Then you'll notice that the fade in of the text (i.e. the action that's supposed to happen on exit) doesn't take place. Suggestions on how to handle that? – Konrad Viltersten Jul 04 '16 at 07:11
  • Looks like an issue (bug?) with the fadeIn() and fadeOut() functions. I've added a new example using animate() that doesn't exhibit the same problem. – Paul LeBeau Jul 04 '16 at 09:42
  • Should the alleged misbehavior be reported somewhere? I'm not familiar with the proper procedures regarding bug reports for jQuery... – Konrad Viltersten Jul 04 '16 at 10:59
  • If you wish you can report it here: https://github.com/jquery/jquery/issues – Paul LeBeau Jul 04 '16 at 13:27
0

What you require is a delay in checking mouse after it leaves an element. See my example using isHover variable with a 300ms delay using setTimeout()

Update: Shorten delay to 50ms, assuming colored areas are side by side.

var isHover = false;
$(".dragon")
  .on("mouseenter", function(target) {
    isHover = true;
    checkHover();
  })
  .on("mouseleave", function(target) {
    isHover = false;
    setTimeout(function(){ checkHover(); }, 50);
  });

function checkHover() {
  if (isHover) {
   $('#indicator').fadeOut();
  } else {
    $('#indicator').fadeIn();
  }
}
div {
  width: 50px;
  height: 50px;
  text-align: center;
}

.uno {
  background-color: blue;
}

.duo {
  background-color: yellow;
}

#indicator {
  color: red;
  font-family: Tahoma;
  font-size: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dragon uno"></div>
<div class="dragon duo"></div>

<div id="indicator"><hr>Enter the dragon!</div>
Alvin K.
  • 4,329
  • 20
  • 25
  • That's a neat work-around. However, due to the specific requirements, I have to fire the visual event immediately upon exit of the areas. In fact, it's so important that I probably rather turn of the fade and just toggle on/off the thingies. I was hoping for some turn on/off of events in combination with a global'ish variable to keep the state. But I fail to see it... Maybe to tired. – Konrad Viltersten Jun 28 '16 at 18:40
  • If the colored areas are side by side, a `50ms` delay will suffice, Have updated code. – Alvin K. Jun 28 '16 at 18:55