I am struggling with a glitch caused by getBoundingClientRect() method. (see fiddle below). The goal is to make a bar following a cursor inside a container. The aforementioned method does not return valid results. I am a beginner in terms of JS - there is most probably an obvious reason behind this. I just can't find the anwswer.
https://jsfiddle.net/aveoL210/3/
var div_moving = document.getElementById('div_moving');
var parent_div = 'parent_div';
var movingDiv = {
getCoords: function(e) {
var rect = e.target.getBoundingClientRect();
var y_pos = rect.top;
console.log(y_pos);
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
document.getElementById(parent_div).addEventListener('mousemove', function(e){
result = movingDiv.getCoords(e);
div_moving.style.top = result 'px';
div_moving.style.display = "initial";
});
document.getElementById(parent_div).addEventListener('mouseleave', function(){
div_moving.style.display = "none";
});
CodePudding user response:
The target
when moving the mouse down will alternate between the moving and parent div
while adding
if(e.target.id !== 'parent_div') return;
guard to the getCoords
function fixes it a little, it's still glitchy
The better solution is to get the rect of the parent_div
, regardless of the e.target
So .. try this
var div_moving = document.getElementById('div_moving');
var parent_div = document.getElementById('parent_div')
var movingDiv = {
getCoords: function(e) {
var rect = parent_div.getBoundingClientRect();
var y_pos = rect.top;
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
parent_div.addEventListener('mousemove', function(e) {
result = movingDiv.getCoords(e);
div_moving.style.top = result 'px';
div_moving.style.display = "initial";
});
parent_div.addEventListener('mouseleave', function() {
div_moving.style.display = "none";
});
#parent_div {
position: relative;
width: 50%;
height: 300px;
margin: 1em auto;
border: 1px solid #333;
background: #f0f0f0;
}
#div_moving {
display: none;
position: absolute;
width: 100%;
height: 5px;
margin: 0;
background: blue;
}
<div id="parent_div">
<div id="div_moving"></div>
</div>
CodePudding user response:
The, what you called "glitch", is actually what is expected to happen. Let me tell you why:
- The line
e.target.getBoundingClientRect()
is the source of the issue, preciselye.target
. - The, so called glitch, happens when the mouse is on top of the
blue line
element and at this pointe.target
no longer points to your#parent_div
and insteade.target
is#div_moving
.
A quick fix would be by caching #parent_div
in a variable so can use it later on, and on the getCoords()
method we simply replace e.target
by that new variable.
Here's a live demo:
var parent_div = document.getElementById('parent_div');
var div_moving = document.getElementById('div_moving');
var movingDiv = {
getCoords: function(e) {
var rect = parent_div.getBoundingClientRect();
var y_pos = rect.top;
//console.log(y_pos);
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
parent_div.addEventListener('mousemove', function(e) {
result = movingDiv.getCoords(e);
div_moving.style.top = result 'px';
div_moving.style.display = "initial";
});
parent_div.addEventListener('mouseleave', function() {
div_moving.style.display = "none";
});
#parent_div {
position: relative;
width: 50%;
height: 300px;
margin: 1em auto;
border: 1px solid #333;
background: #f0f0f0;
}
#div_moving {
display: none;
position: absolute;
width: 100%;
height: 5px;
margin: 0;
background: blue;
}
<div id="parent_div">
<div id="div_moving"></div>
</div>
DISCLAIMAIR: The above demo did not change a lot from the OP's original code which, by the way, can be hugely improved which is out of the scope of my answer.
CodePudding user response:
In getCoords
you want to get parent_div
all the time, so you have to use e.currentTarget
instead of e.target
otherwise, when div_moving
is under the cursor e.target
return div_moving
and all calculation goes wrong, it will move to top and when you move your mouse again all wrong things repeat.
var div_moving = document.getElementById('div_moving');
var parent_div = 'parent_div';
var movingDiv = {
getCoords: function(e) {
console.log(e.target.id)
var rect = e.currentTarget.getBoundingClientRect();
var y_pos = rect.top;
console.log(y_pos);
var y = e.pageY;
y = y - y_pos;
return (y);
}
};
document.getElementById(parent_div).addEventListener('mousemove', function(e){
result = movingDiv.getCoords(e);
div_moving.style.top = result 'px';
div_moving.style.display = "initial";
});
document.getElementById(parent_div).addEventListener('mouseleave', function(){
div_moving.style.display = "none";
});