univers_
univers_

Reputation: 463

Attach to cursor then return to original position

I'm trying to make it so that when hovering over a div, the child of that div attaches to the cursor and when you leave the div, the child returns to its original position.

Here's what I have so far:

$('div').each(function() {  
        var img = $(this).find( "figure" );
    var offset = img.offset();
    var originLeft = offset.left;
    var originTop = offset.top;
    $('div').mousemove(function(e) {
            img.addClass('active');
        img.css({
              transform: 'translateX(' + (e.pageX - originLeft/2 ) + 'px) translateY(' + (e.pageY - originTop) + 'px)'
            });
    }).mouseleave(function() {
            img.removeClass('active');
        img.css({
              transform: 'translateX(0) translateY(0)'
            });
    });
});
div { 
    height: 250px;
    width: 250px;
    background: #eee;
}

div:nth-child(2) {
  background: #ccc;
}

figure {
  display: block;
  height: 50px;
  width: 50px;
  background: blue;
  margin: 0;
  transition: transform 500ms ease;
}

.active {
   transition: none; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
    <figure></figure>
</div>


<div>
    <figure></figure>
</div>

The problems are, it doesn't work if there is more than one of them on the page, and also, the mouseleave event seems buggy: sometimes it takes a second or there is some flickering before it returns to the original position.

Upvotes: 0

Views: 91

Answers (2)

charlietfl
charlietfl

Reputation: 171669

Using mouseenter to add the mousemove listener and removing it in the mouseleave solves most of the issue. The other part is that if the image is directly under the mouse when it leaves the container, the mouse is still on top of a child .

Adding some additional offset to the image position relative to mouse helps remove the rest of the bugginess

$('div').on('mouseenter', function() {
  var img = $(this).find("figure");
  var offset = img.offset();
  var originLeft = offset.left;
  var originTop = offset.top;
  // only listen to move on this instance
  $(this).mousemove(function(e) {
    img.addClass('active').css({
      transform: 'translateX(' + (e.pageX - originLeft / 2) + 'px) translateY(' + (e.pageY+10  - originTop) + 'px)'
    });
  })

}).on('mouseleave', function() {
  // remove the mousemove listener
  $(this).off('mousemove').find("figure").removeClass('active').css({
    transform: 'translateX(0) translateY(0)'
  });
});
div {
  height: 150px;
  width: 150px;
  background: #eee;
  margin-bottom: 30px
}

div:nth-child(2) {
  background: #ccc;
}

figure {
  display: block;
  height: 50px;
  width: 50px;
  background: blue;
  margin: 0;
  transition: transform 500ms ease;
}

.active {
  transition: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <figure></figure>
</div>


<div>
  <figure></figure>
</div>

Upvotes: 3

gaetanoM
gaetanoM

Reputation: 42054

Your issue is in this line:

$('div').mousemove(function(e) {

Change it to:

$(this).on('mousemove', function(e) {

That because you need address the current div element on which you are in the each loop:

$('div').each(function() {

The snippet:

$('div').each(function() {
  var img = $(this).find( "figure" );
  var offset = img.offset();
  var originLeft = offset.left;
  var originTop = offset.top;
  $(this).on('mousemove', function(e) {
      img.addClass('active');
      img.css({
          transform: 'translateX(' + (e.pageX - originLeft/2 ) + 'px) translateY(' + (e.pageY - originTop) + 'px)'
      });
  }).on('mouseout', function(e) {
      img.removeClass('active');
      img.css({
          transform: 'translateX(0) translateY(0)'
      });
  });
});
div {
    height: 250px;
    width: 250px;
    background: #eee;
}

div:nth-child(2) {
    background: #ccc;
}

figure {
    display: block;
    height: 50px;
    width: 50px;
    background: blue;
    margin: 0;
    transition: transform 500ms ease;
}
.active {
    transition: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div>
    <figure></figure>
</div>


<div>
    <figure></figure>
</div>

Upvotes: 1

Related Questions