2

I am developing an app, and have run into a really simple but frustrating issue. Essentially I have a moving element and I want to track when it moves over the mouse. So currently, if the pointer is in the middle of the screen and not moving while the box passes over it NO event will be triggered. Is there any type of mouse or pointer event I could where it would trigger an event when the box passes over it?

Thanks. The simple code example I wrote is below:

<html>
<head>
    <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
</head>
<body>
    <div id="box" style="height:300px;width:300px;background-color:green;position:absolute;top:600px;"></div>
    <script>
    var box = document.getElementById('box');
    box.addEventListener('onmouseover',function(e){
    console.log('im being tagged!')
    });
    $('#box').animate({top: '1px'},3000);
    </script>
</body>
</html>

The events I HAVE tried so far: onmouseover, mouseover, mouseenter, mousemove, pointerenter,pointerover

The pointer events are from a library called pep.

3 Answers3

1

Since you're looking to know when the moving box element is colliding with the mouse, not vice versa, you'll want to set up a looping check for that collision. You'll need to calculate and retain the position of the mouse cursor and use document.elementFromPoint to check if the element over the cursor is the box:

$(document).ready(function() {
  var MouseCoords = function(x, y) {
    this.x = x;
    this.y = y;
  };

  var mousecoords = new MouseCoords(0,0);
  var isTagged = false;

  $( document ).on( "mousemove", function( event ) {
    mousecoords.x = event.pageX;
    mousecoords.y = event.pageY;
  });

  $('#box').animate({top: '1px'},3000);

  function isBoxOverMouse() {
    var collidingElement = document.elementFromPoint(mousecoords.x, mousecoords.y);
    if (collidingElement != null && collidingElement.id == "box") {
      if (!isTagged) {
        isTagged = true;
        console.log("Tag!");
      }
    } else {
      isTagged = false;
    }
  }

  setInterval(isBoxOverMouse, 500);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box" style="height:300px;width:300px;background-color:green;position:absolute;top:600px;"></div>

I have the loop set to fire every 500ms, but that can be changed if that's not your desired frequency. I also set an isTagged variable so the console doesn't report the same collision multiple times, so feel free to remove that if you want the collision reported at every checked interval.

Jonathan Michalik
  • 1,492
  • 14
  • 15
  • bear in mind that this gives you a delay of half-second for the collision detection – blurfus Jun 22 '16 at 22:57
  • Yes, thanks for iterating that. If the loop interval needs to be shortened it can be adjusted by decreasing the value of the second parameter of the `setInterval` call at the end of the javascript snippet. 500ms seemed acceptable for demo purposes – Jonathan Michalik Jun 22 '16 at 23:01
1

Adapting the code from this great answer to detect element collision

I added a function to run while the animation is in progress. Like this

$('#box').animate({
    top: '1px'
  }, {
    duration: 5000,
    // check if box overlaps cursor while animating
    progress: function(promise) {
      isOverlapping(this);
    }
  });

See the jQuery API docs for more details

$(function() {
  var cursorX, cursorY = 0;

  // tracks mouse position and updates its x,y coordinates
  $(document).on('mousemove', function(e) {
    cursorX = e.pageX;
    cursorY = e.pageY;
    $("#cursor").text("[X: " + e.pageX + ", Y: " + e.pageY + "]");
    isOverlapping("#box");
  });

  // detects if two elements overlap
  var overlaps = (function() {
    function getPositions(elem) {
      var pos, width, height;
      pos = $(elem).position();
      width = $(elem).width();
      height = $(elem).height();
      return [
        [pos.left, pos.left + width],
        [pos.top, pos.top + height]
      ];
    }

    function comparePositions(p1, p2) {
      var r1, r2;
      r1 = p1[0] < p2[0] ? p1 : p2;
      r2 = p1[0] < p2[0] ? p2 : p1;
      return r1[1] > r2[0] || r1[0] === r2[0];
    }

    return function(b) {
      // making cursor 2x2 pixels
      var pos1 = [
          [cursorX, cursorX + 2],
          [cursorY, cursorY + 2]
        ],
        pos2 = getPositions(b);
      return comparePositions(pos1[0], pos2[0]) && comparePositions(pos1[1], pos2[1]);
    };
  })();

  // updates status if the box overlaps the cursor
  var isOverlapping = function(elem){
    if (overlaps(elem)) {
        $("#boxPos").text("Overlaps");
        $("#boxPos").addClass("yes");
        $("#boxPos").removeClass("no");
      } else {
        $("#boxPos").text("No overlap");
        $("#boxPos").addClass("no");
        $("#boxPos").removeClass("yes");
      }
    }

  $('#box').animate({
    top: '1px'
  }, {
    duration: 5000,
    // check if box overlaps cursor while animating
    progress: function(promise) {
      isOverlapping(this);
    }
  });
});
#cursor,
#boxPos {
  float: right;
  display: block;
}
.yes {
  background-color: green;
}
.no {
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box" style="height:150px;width:150px;background-color:green;position:absolute;top:600px;"></div>
<div id="cursor"></div>
<br/>
<div id="boxPos"></div>
<br/>
Community
  • 1
  • 1
blurfus
  • 13,485
  • 8
  • 55
  • 61
0

Since you are using JQuery, you can use the mousemove event handler attached to the HTML body element. This will give you the mouse position, which you can then use to determine when the mouse is intersecting the box.

<html>
<head>
    <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
</head>
<body>
    <div id="box" style="height:300px;width:300px;background-color:green;position:absolute;top:600px;"></div>
    <script>
    $(document).ready(function() {
        var mousePos = {x:0, y:0}
        $('html').mousemove(function(event) {
            mousePos.x = event.clientX
            mousePos.y = event.clientY
        })
        $('#box').animate({top: '1px'},{
            duration: 3000,
            step: function() {
                console.log(parseInt($('#box').css('top')) <= mousePos.y)
            }
        });
    })
    </script>
</body>
</html>
GHandel
  • 172
  • 2
  • 3
  • 13
  • I think OP wants to detect it even when the mouse does not move (so no `mousemove` event will be triggered) – blurfus Jun 22 '16 at 22:59