'mouseenter' and 'mouseleave' event keeps triggering with div as cursor

时间:2018-12-19 11:25:07

标签: javascript jquery html css

I made a 'custom cursor' by hiding the users cursor and displaying a div where the original cursor would normally be displayed on the screen.

Now the problem is I'd like to add some animations when hovering over an element (e.g. scale the 'cursor', or in this case the div that acts as the cursor).
In this example I made a button, and gave it a 'mouseenter' and 'mouseleave' event.
When you enter the button with your cursor, I console.log("enter");
When you leave the button, console.log("leave");

You can quickly see the problem: the two events are being triggered numerous times when hovering over the button, while the cursor is not actually leaving the element.
Also note that this problem doesn't occur when you're very slowly hovering to the left, or to the top (in a straight line), which is probably because of the 'left: e.pageX and top: e.pageY' piece of code in the script.

What can you do to fix this so the two events trigger properly?

$(document).ready(function() {

  var cursor = $(".cursor");

  /* Cursor */
  $(document).on("mousemove", function(e) {
    cursor.css({
      left: e.pageX,
      /*Or clientX and clientY */
      top: e.pageY,
    });
  });

  /* Button */
  $(".btn").on("click", function(e) {
    e.preventDefault();
  });

  $(".btn").on("mouseenter", function() {
    console.log("entered");
  });

  $(".btn").on("mouseleave", function() {
    console.log("left");
  });
});
* {
  cursor: none;
}

.cursor {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  position: absolute;
  background-color: black;
}

.btn {
  text-decoration: none;
  font-family: sans-serif;
  font-weight: bold;
  text-transform: uppercase;
  color: black;
  background-color: white;
  border: 4px solid black;
  padding: 0.5rem 0.8rem;
  display: inline-block;
  margin: 100px 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!--Button-->
<div class="center marginB">
  <a id="startChat" class="btn">Button</a>
</div>

<!--Cursor-->
<div class="cursor"></div>

3 个答案:

答案 0 :(得分:1)

Add pointer-events: none to your .cursor to make the cursor (black dot) never a target of any mouse events, and so it will never affect the mouse enter and mouse leave events. You can read more about pointer events here

See working example below:

$(document).ready(function() {

  var cursor = $(".cursor");

  /* Cursor */
  $(document).on("mousemove", function(e) {
    cursor.css({
      left: e.pageX,
      /*Or clientX and clientY */
      top: e.pageY,
    });
  });

  /* Button */
  $(".btn").on("click", function(e) {
    e.preventDefault();
  });

  $(".btn").on("mouseenter", function() {
    console.log("entered");
  });
  
  $(".btn").on("mouseleave", function() {
    console.log("left");
  });
});
* {
  cursor: none;
}

.cursor {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  position: absolute;
  background-color: black;
  pointer-events: none;
}

.btn {
  text-decoration: none;
  font-family: sans-serif;
  font-weight: bold;
  text-transform: uppercase;
  color: black;
  background-color: white;
  border: 4px solid black;
  padding: 0.5rem 0.8rem;
  display: inline-block;
  margin: 100px 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--Button-->
<div class="center marginB">
  <a id="startChat" class="btn">Button</a>
</div>

<!--Cursor-->
<div class="cursor"></div>

答案 1 :(得分:1)

The problem is because there is a delay between the actual hidden cursor being moved by the user and the .cursor element moving to match its position, simply due to the performance of JS. As such the real cursor can, for a split second, go outside the bounds of .cursor and cause a mouseenter on the underlying button. The .cursor is then moved and the actual cursor then causes a mouseleave on the button as it's now over the .cursor element.

The simplest workaround would be to use CSS to set the cursor style to an image which matches the dot, as it performs far better than JS:

$(document).ready(function() {
  $(".btn").on("click", function(e) {
    e.preventDefault();
  });

  $(".btn").on("mouseenter", function() {
    console.log("entered");
  });

  $(".btn").on("mouseleave", function() {
    console.log("left");
  });
});
* {
  cursor: url('https://i.imgur.com/SyBk5p5.png'), auto;
}

.cursor {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  position: absolute;
  background-color: black;
}

.btn {
  text-decoration: none;
  font-family: sans-serif;
  font-weight: bold;
  text-transform: uppercase;
  color: black;
  background-color: white;
  border: 4px solid black;
  padding: 0.5rem 0.8rem;
  display: inline-block;
  margin: 100px 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="center marginB">
  <a id="startChat" class="btn">Button</a>
</div>

答案 2 :(得分:0)

You should be able to do this with just pure CSS.

Since the div that houses your button and cursor are both part of the body they are siblings of the same container. You could use this to detect the hover on the button and then in turn change the styles of the cursor.

.marginB:hover ~ .cursor { background-color: yellow; }

https://jsfiddle.net/4nrtgx8o/

EDIT: If you remove your 100px margins from your button the hover effect wouldn't happen until you actually hover on the button. With your current CSS the button itself appears much smaller than the space it actually occupies as a piece of code. That's why the hover action happens before actually reaching the button.