Search code examples
jqueryloopscursormove

Multiple Divs follow cursor all with variable speeds


I've done some research on how to get a div/graphic to follow the cursor - Resource Here - I am trying to create this effect for multiple divs where each div has it's own random speed where some elements are lagging behind more than others. I have created a JS Fiddle to show the current progress, you can see it kind of works to some extend. But I am hoping to achieve a more dramatic effect than what I currently have.

JS Fiddle

Code HTML

<div class="container">
  <div class="following blue"></div>
  <div class="following red"></div>
  <div class="following yellow"></div>
  <div class="following orange"></div>
  <div class="following green"></div>
  <div class="following purple"></div>
  <div class="following pink"></div>
</div>

Code JS

var mouseX = 0,
    mouseY = 0,
    limitX = 400 - 15,
    limitY = 550 - 15;

$(window).mousemove(function(e) {
    // with the math subtractnig the boundary  
    mouseX = Math.min(e.pageX, limitX);
    mouseY = Math.min(e.pageY, limitY);
});

// cache the selector
var followers = $(".following");
var x_pixels = 0,
    y_pixels = 0;
var loop = setInterval(function() {

    // Loop through each follower to move and have random speeds
    followers.each(function() {
      // Set a max Number to allow for the randomIntFromInterval
      // function to work
      var max = followers.length * 15;
      var min = followers.length;

      x_pixels += (mouseX - x_pixels) / randomIntFromInterval(min, max);
      y_pixels += (mouseY - y_pixels) / randomIntFromInterval(min, max);

    $(this).css({
      left: x_pixels,
      top: y_pixels
    });

  });

 }, 40);

function randomIntFromInterval(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

Any advice on how to do this is greatly appreciated. Thanks!


Solution

  • Let's start with why it isn't too random. First off these calculations are run for each dot every 40ms. This has interesting consequences.

    x_pixels += (mouseX - x_pixels) / randomIntFromInterval(min, max);
    y_pixels += (mouseY - y_pixels) / randomIntFromInterval(min, max);
    

    Say the blue dot gets a set of random numbers {1, 4, 7, 8, 4, 3, 10, 6, 6} and the red dot gets a set of random numbers {8, 7, 5, 4, 5, 7, 9, 4, 3}. The problem is the average of these is going to be the same (5.44 and 5.77 respectively). Because the movements are happening so fast they have a little jitter but their bigger movements tend to be the same.

    The second problem is that you are using the same x_pixels and y_pixels for each dot. You declare this on top:

    var x_pixels = 0,
    y_pixels = 0;
    

    But then you don't ever go get the current value back from the dot. You recycle them by += but each dot shares the same position.

    I have two solutions for you as this problem is fairly broad and could be interpreted multiple ways. Both of these solutions address the problems listed above by assigning a friction coefficient that stays with the dot. The first example keeps the random friction for the lifetime of the dot, the second changes the friction coefficient every so often.

    jsfiddle.net/e3495jmj/1 - First solution

    jsfiddle.net/e3495jmj/2 - Second solution

    Cheers!