Avago24
Avago24

Reputation: 33

jQuery hover is too slow

Please run the snippet and drag you mouse over the bar to make it red. If you drag the mouse very slowly, you will fill it red, but if you move it fast, there will be white holes in it.

How to fix it? (the white holes)

I want to make a bar divided into 500 parts and if you hover it, it becomes red and being able to drag fast and fill it without holes.

Any help appreciated :)

$(function() {

  var line = $("#line");
  
  for ( var i = 0; i < 500; i++) {
  
    line.append('<div class="tile" id="t'+(i+1)+'"></div>');
    
  }
  
  var tile = $(".tile");
  
  tile.hover (
    function() { //hover-in
      $(this).css("background-color","red");
    },
    function() { //hover-out
      
    }
   );
    
});
#line{
  height: 50px;
  background-color: #000;
  width: 500px;
}
.tile {
  height: 50px;
  float: left;
  background-color: #ddd;
  width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>

Upvotes: 3

Views: 927

Answers (3)

ThatCoderGuy
ThatCoderGuy

Reputation: 677

Another solution makes use of jQuery's mousemove method. This allows the bar to go both forward and backwards, simply following the cursors position.

This detects movement inside of the div, then I calculate the position of the cursor within the div as a percentage and apply it as the width of the red bar.

    $( ".bar" ).mousemove(function( event ) {
      var xCord = event.pageX;
      xPercent = (xCord + $('.pct').width()) / $( document ).width() * 100;
  
      $('.pct').width(xPercent+'%');
  
    });

    
    
    .bar{
        background:'#999999';
        width:50%;
        height:50px;
 
    }

    .pct{
        height:100%;
        background:red;
        width:0%;
    }
    

    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js">
    </script>
    
    <div class="bar" style="background:#999999">
        <div class="pct"></div>
    </div>
    

Upvotes: 0

Spencer Wieczorek
Spencer Wieczorek

Reputation: 21575

With your design one way would be to iterate over the first to your current hovered element and fill it, which would lead no spaces. That said you may want to consider using the HTML5 Canvas and drawing a rectangle from 0 to your mouse position, which will perform significantly faster.

$(function() {

  var line = $("#line");
  
  for ( var i = 0; i < 500; i++) {
  
    line.append('<div class="tile" id="t'+(i+1)+'"></div>');
    
  }
  
  var tile = $(".tile");
  
  tile.hover (
    function() { //hover-in
      var self = this;
      $("#line").children().each(function(){
        $(this).css("background-color","red");
        if(this == self) return false;
      });
    },
    function() { //hover-out
      
    }
   );
    
});
#line{
  height: 50px;
  background-color: #000;
  width: 500px;
}
.tile {
  height: 50px;
  float: left;
  background-color: #ddd;
  width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>


Edit

Below is an example doing the same task but using the HTML 5 Canvas:

$("#line").mousemove(function(e){
  var canvas = $(this)[0];
  var ctx = canvas.getContext("2d");
  var rect = canvas.getBoundingClientRect()
  var x = e.clientX - rect.left;
  ctx.fillStyle="red";
  ctx.fillRect(0, 0, x, canvas.height);
});
#line{ background-color: #ddd; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="line" width=500 height=50 ></canvas>

Upvotes: 1

Kresimir Pendic
Kresimir Pendic

Reputation: 3614

This is another approach with nextUntil to select siblings..

$(function() {

  var line = $("#line");
  
  for ( var i = 0; i < 500; i++) {
  
    line.append('<div class="tile" id="t'+(i+1)+'"></div>');
    
  }
  
  var tile = $(".tile");
  
  line.on( 'mouseover', function(ev){
    $('.tile').first().nextUntil( $('.tile').eq(ev.pageX) ).css("background-color","red");
  });

  line.on( 'mouseleave', function(ev){
    $('.tile').css("background-color","#ddd");
  });

});
#line{
  height: 50px;
  background-color: #000;
  width: 500px;
}
.tile {
  height: 50px;
  float: left;
  background-color: #ddd;
  width: 1px;
}
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<div id="line"></div>

Upvotes: 0

Related Questions