Search code examples
javascriptjqueryrandomjquery-easing

Random JQuery's .animate easing


I've been searching for this for some time and I can't seem to find what I need. I know you can make custom easing, but I have no idea how. I am doing a horse race (JQuery moves all the horses). I need them to go in random speeds, but need to complete the animation in given duration. For example:

Horse1:
[0-1-3-4-5-4-4-5-3-2-8-9-8-4-3-2-1-0]
Horse2:
[4-4-2-1-1-1-4-9-9-9-8-6-5-4-3-2-5-6]
Horse3:
[2-3-4-5-5-5-5-6-7-8-7-4-5-1-2-4-5-8]

Numbers here represent the velocity (speed) of the element. I've seen a special plugin for easings, but there is no easing like the one I want.

Any help is appreciated. Thanks, Nedas


Solution

  • I provide an example below showing how you can use jQuery's animate function to "race" three "horses" using the data you provided. However, this is using the standard "linear" easing function that jQuery provides, with the animate function called multiple times for each "horse".

    Technically, you could create custom easing functions to move the horses, incorporating your speed data into the easing functions themselves. However, I don't think this would be a good way to approach the problem for several reasons:

    • You would have to code a different hard-coded easing function for each of the three horses, because easing functions can't be programmed to take input parameters, i.e. the speed parameters.
    • Easing functions cannot be stored in arrays, so you couldn't call myEasingFunction[0], myEasingFunction[1], etc., but would have to use individual functions, e.g. myEasingFunction0, myEasingFunction1, etc. That's not very flexible.
    • Because you only want one horse to "win", you would have to make an ugly choice between (1) having two of your three custom easing functions not go to 100% of the total "race" distance, or (2) having to separately provide a different final distance for each horse, which would sort of defeat the purpose of creating custom easing functions, i.e. having to put some form of the data in two different places.

    In any case, if you want some info about creating custom easing functions, check out this other Stack Overflow answer.

    var horseSpeeds = [
      [0, 1, 3, 4, 5, 4, 4, 5, 3, 2, 8, 9, 8, 4, 3, 2, 1, 0],
      [4, 4, 2, 1, 1, 1, 4, 9, 9, 9, 8, 6, 5, 4, 3, 2, 5, 6],
      [2, 3, 4, 5, 5, 5, 5, 6, 7, 8, 7, 4, 5, 1, 2, 4, 5, 8]
    ];
    
    var $horses = $("div");
    var raceStepNum = 0;
    var dist = [0, 0, 0];
    
    var moveHorses = function moveHorses() {
      $horses.each(function(horseNum, horse) {
        dist[horseNum] += (horseSpeeds[horseNum][raceStepNum]) * 4;
        $(horse).animate({
          marginLeft: dist[horseNum]
        }, 100, "linear", function() {
          if (horseNum === 0) {
            raceStepNum += 1;
            if (raceStepNum < horseSpeeds[0].length) {
              moveHorses();
            }
          }
        });
      });
    }
    
    $("button#startRace").click(moveHorses);
    $("button#resetRace").click(function() {
      $("div").css({marginLeft: 0});
      dist = [0, 0, 0];
      raceStepNum = 0;
    });
    div {
      width: 20px;
      height: 20px;
      margin-bottom: 10px;
    }
    #horse0 {
      background-color: blue;
    }
    #horse1 {
      background-color: red;
    }
    #horse2 {
      background-color: green;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button id="startRace">Start race</button><button id="resetRace">Reset race</button>
    <div id="horse0"></div>
    <div id="horse1"></div>
    <div id="horse2"></div>