Home > Blockchain >  What causes the glitch in getBoundingClientRect()?
What causes the glitch in getBoundingClientRect()?

Time:09-20

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, precisely e.target.
  • The, so called glitch, happens when the mouse is on top of the blue line element and at this point e.target no longer points to your #parent_div and instead e.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";
});
  • Related