LaVOZs

The World’s Largest Online Community for Developers

'; javascript - How to animate an element to follow mouse movements within a div? - LavOzs.Com

I'm attempting to make an element to follow mouse movements within the constraints of a container div using jQuery animate. When the mouse moves, the element changes to having absolute positioning that matches its current position, and then moves toward the position of the mouse, but within the div.

I can't seem to get the vertical positioning right, though: the element is always higher than the container, and sometimes it moves in the opposite direction of what it should (i.e., the mouse moves down, and element moves up). I've had no problems with horizontal positioning.

Here's the code:

var executed = false;
var dronePos = $("#drone").offset().top;

$("body").mousemove(function(event) {

    var x;
    var y;

    //Vertical positioning: If the mouse position is greater than or equal to the left offset of the drone container, and less than or equal to the left offset of the drone container plus the width (if it falls within the drone container)

    if (event.pageX >= $("#droneContainer").offset().left && event.pageX <= $("#droneContainer").offset().left + $("#droneContainer").width()){
        x = event.pageX;

    } else { //if it's to the left
        if (event.pageX < $("#droneContainer").offset().left){
            x = $("#droneContainer").offset().left; 
        }
        else { //if it's to the right
            x = $("#droneContainer").offset().left + $("#droneContainer").width();
        }
    }   

    //Horizontal positioning: If the mouse position is greater than or equal to the to offset of the drone container, and less than or equal to the top offset of the drone container plus the height (if it falls within the drone container)

    if (event.pageY >= $("#droneContainer").offset().top && event.pageY <= $("#droneContainer").offset().top + $("#droneContainer").height()){
        y = event.pageY - dronePos;
    } else { //if it's above
        if (event.pageY < $("#droneContainer").offset().top){
            y = $("#droneContainer").offset().top - dronePos;   
        } else { //if it's below
            y = ($("#droneContainer").offset().top + $("#droneContainer").height()) - dronePos;
        }
    }

    if (executed == false){
        executed = true;
        var position = $("#drone").position();
        $("#drone").css({top: position.top, left: position.left, position:"absolute"}); 
    }

    $("#drone").stop().animate({
        left: x, 
        top: y
    }, 800, "swing");

    dronePos = $("#drone").offset().top;

});

Any help much appreciated! 🙏

It's hard to tell what is really going wrong in your code example, so I've tried to make a lighter version which, hopefully, does what your own script should do.

Also in my opinion, refrain from using jQuery animate. CSS has become very powerful indeed and can do a lot of the heavy lifting on positioning and transitions for you.

I hope this helps you out. If you have any questions, please let me know.

var $container = $('.container');
var $drone = $('.drone');
var droneCenter = {
  x: $drone.width() / 2,
  y: $drone.height() / 2
};

$container.on('mousemove', function(event) {
  $drone.css('transform', `translate3d(${event.offsetX - droneCenter.x}px, ${event.offsetY - droneCenter.y}px, 0)`);
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: grid;
  align-items: safe center;
  justify-content: safe center;
}

.wrapper {
  width: 100vw;
  height: 100vh;
  max-width: 1000px;
  max-height: 1000px;
  padding: 15px;
}

.container {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #f7f7f7;
  border: 1px solid #f0f0f0;
  border-radius: 5px;
  overflow: hidden;
}

.drone {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 25px;
  height: 25px;
  background-color: red;
  border-radius: 50%;
  transition: transform 800ms ease-out;
  will-change: transform;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="container">
    <div class="drone"></div>
  </div>
</div>