Track mouseover event with moving elements - javascript

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.

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.

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/>

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>

Related

Angular: following mouse position on scroll

I have an element following my mouse around the page on mousemove. It works fine but when I scroll the page, the mouse does not follow, how do I fix it so that it follows it on scroll?
https://stackblitz.com/edit/angular-lg2p6f?file=src/app/app.component.html
HTML:
<div
class="wrapper"
(mouseenter)="enter()"
(mousemove)="move($event)"
(mouseleave)="leave()"
>
<p>Start editing to see some magic happen :)</p>
<div class="sites-circle" [ngClass]="mouseMove ? 'onMove' : 'notMove'">
hello
</div>
</div>
TS:
enter(source: string) {
this.tooltip.classList.add('show');
}
mouseStopped() {
this.mouseMove = false;
console.log("mousemove: " + this.mouseMove);
}
move(e: { pageX: number; pageY: number }) {
this.mouseMove = true;
console.log("mousemove: " + this.mouseMove);
var timer;
clearTimeout(timer);
timer = setTimeout(this.mouseStopped, 300);
const tooltipStyle = this.tooltip.style;
tooltipStyle.left = e.pageX + 'px';
tooltipStyle.top = e.pageY + 'px';
}
leave() {
this.tooltip.classList.remove('show');
}
CSS:
.sites-circle.onMove {
transform: scale(3);
}
.sites-circle.notMove {
transform: scale(1) !important;
}
According to this answer, we cannot get mouse current position on scroll we can just get how much it scrolled relative to last position.
For your problem, this can be realized as follows (here is your updated stackblitz):
Add a (window:scroll) listener to your <div>.
<div
class="wrapper"
(mouseenter)="enter()"
(mousemove)="move($event)"
(window:scroll)="onScroll($event)"
(mouseleave)="leave()"
>
Hold the last position, e.g.:
lastPosition = {
x: undefined,
y: undefined,
};
...
// inside your move() function
this.lastPosition.x = e.pageX;
this.lastPosition.y = e.pageY;
Hold the last known "move" page offset:
lastMovePageOffset = {
x: undefined,
y: undefined,
};
...
// inside your move() function
this.lastMovePageOffset.y = window.pageYOffset;
Use the difference of the current scroll position and the last known page "move" page offset to calculate the new position:
onScroll(e: any) {
if (this.lastPosition.y !== undefined) {
let pageOffsetY = 0;
if (this.lastMovePageOffset.y !== undefined) {
pageOffsetY = window.pageYOffset - this.lastMovePageOffset.y;
}
this.tooltip.style.top = this.lastPosition.y + pageOffsetY + 'px';
}
}
This can be handled similarly with the x-Position. The solution works as soon as the cursor is moved once before scrolling (caused by the general problem described in the first sentence).
Good luck!

How can I create a click and drag to change the width of an object with jQuery?

I have an object that I want to change the width of when you click on it and drag right or left. Adding to the width or taking away from it as you move the mouse (or finger).
<style>
#changeMe {width:300px; height: 200px;}
</style>
<div id="changeMe">
Some Content
</div>
<script>
$('#changeMe').mousedown(function(){
//Some Code?????
});
</script>
What you want to do is track the x co-ords of the mouse. If greater than they were before, increase size, if lower, decrease the size.
Not tested but the below should be inspiration.
var oldXPos = 0;
var isDragging = false;
$(document).mousemove(function(event) {
if (isDragging)
{
var difference = event.pageX - oldXPos;
// Do something with this value, will be an int related to how much it's moved
// ie $('#changeMe').css.width += difference;
}
oldXPos = event.pageX;
});
$('#changeMe').mousedown(function() {
isDragging = true;
})
$('#changeMe').mouseup(function() {
isDragging = false;
})
You just need a resizable({}) effect .
$('#changeMe').resizable({});
You can look at this article
Resizable
$(function() {
$('.testSubject').resizable();
});
or
#changeMe {width:300px; height: 200px; border: 1px solid black;}
<body>
<div id="changeMe">
Some Content
</div>
</body>
$('#changeMe').resizable({});
Or
$(function(){
$('img[src*=small]').toggle(
function() {
$(this).attr('src',
$(this).attr('src').replace(/small/,'medium'));
},
function() {
$(this).attr('src',
$(this).attr('src').replace(/medium/,'large'));
},
function() {
$(this).attr('src',
$(this).attr('src').replace(/large/,'small'));
}
);
});
If I understand your question correctly, that you want to be able to dynamically increase/decrease the size of the object as it moves along the x-axis, I recommend that you use $('#changeMe').offset() inside the jQuery UI drag event.
You can create a formula that you want to use based on an initial offset, and the new offset to size your container by $('#changeMe').css({ width: X, height: Y });, and insert whatever your X and Y values are in pixels.
Edited for further elaboration with code:
var initX = 0;
var initW = 0;
$('#changeMe').draggable({
start: function() {
initX = $(this).offset().left;
initW = $(this).width();
},
drag: function() {
var deltaX = initX - $(this).offset().left;
$(this).css({ width: initW + deltaX });
}
});
If you used that as your base, it's a very nice and simple solution for your application.

Create a draggable div in native javascript [duplicate]

This question already has answers here:
Moveable/draggable <div>
(9 answers)
Closed 5 years ago.
I want to create a movable/draggable div in native javascript without using jquery and libraries. Is there a tutorial or anythign?
OK, here's my personal code that I use for lightweight deployments (projects where using a library is either not allowed or overkill for some reason). First thing first, I always use this convenience function so that I can pass either an id or the actual dom element:
function get (el) {
if (typeof el == 'string') return document.getElementById(el);
return el;
}
As a bonus, get() is shorter to type than document.getElementById() and my code ends up shorter.
Second realize that what most libraries are doing is cross-browser compatibility. If all browsers behave the same the code is fairly trivial. So lets write some cross-browser functions to get mouse position:
function mouseX (e) {
if (e.pageX) {
return e.pageX;
}
if (e.clientX) {
return e.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
}
return null;
}
function mouseY (e) {
if (e.pageY) {
return e.pageY;
}
if (e.clientY) {
return e.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
}
return null;
}
OK, the two functions above are identical. There're certainly better ways to write them but I'm keeping it (relatively) simple for now.
Now we can write the drag and drop code. The thing I like about this code is that everything's captured in a single closure so there are no global variables or helper functions littering the browser. Also, the code separates the drag handle from the object being dragged. This is useful for creating dialog boxes etc. But if not needed, you can always assign them the same object. Anyway, here's the code:
function dragable (clickEl,dragEl) {
var p = get(clickEl);
var t = get(dragEl);
var drag = false;
offsetX = 0;
offsetY = 0;
var mousemoveTemp = null;
if (t) {
var move = function (x,y) {
t.style.left = (parseInt(t.style.left)+x) + "px";
t.style.top = (parseInt(t.style.top) +y) + "px";
}
var mouseMoveHandler = function (e) {
e = e || window.event;
if(!drag){return true};
var x = mouseX(e);
var y = mouseY(e);
if (x != offsetX || y != offsetY) {
move(x-offsetX,y-offsetY);
offsetX = x;
offsetY = y;
}
return false;
}
var start_drag = function (e) {
e = e || window.event;
offsetX=mouseX(e);
offsetY=mouseY(e);
drag=true; // basically we're using this to detect dragging
// save any previous mousemove event handler:
if (document.body.onmousemove) {
mousemoveTemp = document.body.onmousemove;
}
document.body.onmousemove = mouseMoveHandler;
return false;
}
var stop_drag = function () {
drag=false;
// restore previous mousemove event handler if necessary:
if (mousemoveTemp) {
document.body.onmousemove = mousemoveTemp;
mousemoveTemp = null;
}
return false;
}
p.onmousedown = start_drag;
p.onmouseup = stop_drag;
}
}
There is a reason for the slightly convoluted offsetX/offsetY calculations. If you notice, it's just taking the difference between mouse positions and adding them back to the position of the div being dragged. Why not just use the mouse positions? Well, if you do that the div will jump to the mouse pointer when you click on it. Which is a behavior I did not want.
You can try this
HTML
<div id="one" style="height:50px; width:50px; border:1px solid #ccc; background:red;">
</div>
Js Script for draggable div
window.onload = function(){
draggable('one');
};
var dragObj = null;
function draggable(id)
{
var obj = document.getElementById(id);
obj.style.position = "absolute";
obj.onmousedown = function(){
dragObj = obj;
}
}
document.onmouseup = function(e){
dragObj = null;
};
document.onmousemove = function(e){
var x = e.pageX;
var y = e.pageY;
if(dragObj == null)
return;
dragObj.style.left = x +"px";
dragObj.style.top= y +"px";
};
Check this Demo
This code corrects the position of the mouse (so the dragged object doesn't jump when you start dragging) and works with touch screens/phones as well
var dragObj = null; //object to be moved
var xOffset = 0; //used to prevent dragged object jumping to mouse location
var yOffset = 0;
window.onload = function()
{
document.getElementById("menuBar").addEventListener("mousedown", startDrag, true);
document.getElementById("menuBar").addEventListener("touchstart", startDrag, true);
document.onmouseup = stopDrag;
document.ontouchend = stopDrag;
}
function startDrag(e)
/*sets offset parameters and starts listening for mouse-move*/
{
e.preventDefault();
e.stopPropagation();
dragObj = e.target;
dragObj.style.position = "absolute";
var rect = dragObj.getBoundingClientRect();
if(e.type=="mousedown")
{
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
}
else if(e.type=="touchstart")
{
xOffset = e.targetTouches[0].clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
function dragObject(e)
/*Drag object*/
{
e.preventDefault();
e.stopPropagation();
if(dragObj == null) return; // if there is no object being dragged then do nothing
else if(e.type=="mousemove")
{
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
}
else if(e.type=="touchmove")
{
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
}
}
function stopDrag(e)
/*End dragging*/
{
if(dragObj)
{
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
div{height:400px; width:400px; border:1px solid #ccc; background:blue; cursor: pointer;}
<div id="menuBar" >A</div>
<div draggable=true ondragstart="event.dataTransfer.setData('text/plain', '12345')">
drag me
</div>
<div ondragover="return false;" ondrop="this.innerHTML=event.dataTransfer.getData('text/plain')">
drop on me
</div>

draggable without jQuery ui

How to make a element draggable without using jQuery UI?
I have this code:
<script type="text/javascript">
function show_coords(event)
{
var x=event.clientX;
var y=event.clientY;
var drag=document.getElementById('drag');
drag.style.left=x;
drag.style.top=y
}
</script>
<body style="height:100%;width:100%" onmousemove="show_coords(event)">
<p id="drag" style="position:absolute">drag me</p>
</body>
The problem is that I want to drag while the user the pressing the mouse button. I tried onmousedown but results were negative.
It will be quite easy as you get the concept.
function enableDragging(ele) {
var dragging = dragging || false, //Setup a bunch of variables
x, y, Ox, Oy,
enableDragging.z = enableDragging.z || 1,
current;
ele.onmousedown = function(ev) { //When mouse is down
current = ev.target;
dragging = true; //It is dragging time
x = ev.clientX; //Get mouse X and Y and store it
y = ev.clientY; // for later use.
Ox = current.offsetLeft; //Get element's position
Oy = current.offsetTop;
current.style.zIndex = ++enableDragging.z; //z-index thing
window.onmousemove = function(ev) {
if (dragging == true) { //when it is dragging
var Sx = ev.clientX - x + Ox, //Add the difference between
Sy = ev.clientY - y + Oy; // 2 mouse position to the
current.style.top = Sy + "px"; // element.
current.style.left = Sx + "px";
return false; //Don't care about this.
}
};
window.onmouseup = function(ev) {
dragging && (dragging = false); //Mouse up, dragging done!
}
};
}
enableDragging(document.getElementById("drag")); //draggable now!
var ele = document.getElementsByTagName("div");
for(var i = 0; i < ele.length; i++){ //Every div's is draggable
enableDragging(ele[i]); // (only when its "position"
} // is set to "absolute" or
// "relative")
http://jsfiddle.net/DerekL/NWU9G/
The reason why your code is not working is because the <div> will always follow where your cursor goes, and you are not actually dragging it. The top left corner will always follow your cursor, and this is not we wanted.
UPDATE
Now if you only want a grabber or something similar, just change this part of the script:
ele.onmousedown = function(ev) {
current = ev.target;
to
var grabber = document.createElement("div");
grabber.setAttribute("class", "grabber");
ele.appendChild(grabber);
grabber.onmousedown = function(ev) {
current = ev.target.parentNode;
Now you can only click on the grabber to start the dragging process.
http://jsfiddle.net/DerekL/NWU9G/7/

Make an image follow mouse pointer

I need a rocket to follow the movements of the mouse pointer on my website. This means it should rotate to face the direction of motion, and if possible, accelerate depending on the distance it has to cover.
Is this even possible ? jquery perhaps ?
by using jquery to register .mousemove to document to change the image .css left and top to event.pageX and event.pageY.
example as below
http://jsfiddle.net/BfLAh/1/
$(document).mousemove(function(e) {
$("#follow").css({
left: e.pageX,
top: e.pageY
});
});
#follow {
position: absolute;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="follow"><img src="https://placekitten.com/96/140" /><br>Kitteh</br>
</div>
updated to follow slowly
http://jsfiddle.net/BfLAh/3/
for the orientation , you need to get the current css left and css top and compare with event.pageX and event.pageY , then set the image orientation with
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
for the speed , you can set the jquery .animation duration to certain amount.
Ok, here's a simple box that follows the cursor
Doing the rest is a simple case of remembering the last cursor position and applying a formula to get the box to move other than exactly where the cursor is. A timeout would also be handy if the box has a limited acceleration and must catch up to the cursor after it stops moving. Replacing the box with an image is simple CSS (which can replace most of the setup code for the box). I think the actual thinking code in the example is about 8 lines.
Select the right image (use a sprite) to orientate the rocket.
Yeah, annoying as hell. :-)
function getMouseCoords(e) {
var e = e || window.event;
document.getElementById('container').innerHTML = e.clientX + ', ' +
e.clientY + '<br>' + e.screenX + ', ' + e.screenY;
}
var followCursor = (function() {
var s = document.createElement('div');
s.style.position = 'absolute';
s.style.margin = '0';
s.style.padding = '5px';
s.style.border = '1px solid red';
s.textContent = "🚀"
return {
init: function() {
document.body.appendChild(s);
},
run: function(e) {
var e = e || window.event;
s.style.left = (e.clientX - 5) + 'px';
s.style.top = (e.clientY - 5) + 'px';
getMouseCoords(e);
}
};
}());
window.onload = function() {
followCursor.init();
document.body.onmousemove = followCursor.run;
}
#container {
width: 1000px;
height: 1000px;
border: 1px solid blue;
}
<div id="container"></div>
Here's my code (not optimized but a full working example):
<head>
<style>
#divtoshow {position:absolute;display:none;color:white;background-color:black}
#onme {width:150px;height:80px;background-color:yellow;cursor:pointer}
</style>
<script type="text/javascript">
var divName = 'divtoshow'; // div that is to follow the mouse (must be position:absolute)
var offX = 15; // X offset from mouse position
var offY = 15; // Y offset from mouse position
function mouseX(evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
function mouseY(evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}
function follow(evt) {
var obj = document.getElementById(divName).style;
obj.left = (parseInt(mouseX(evt))+offX) + 'px';
obj.top = (parseInt(mouseY(evt))+offY) + 'px';
}
document.onmousemove = follow;
</script>
</head>
<body>
<div id="divtoshow">test</div>
<br><br>
<div id='onme' onMouseover='document.getElementById(divName).style.display="block"' onMouseout='document.getElementById(divName).style.display="none"'>Mouse over this</div>
</body>

Categories