简体   繁体   中英

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.

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>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM