<div class="stars-container" id="stars-container">
  <div data-uniq-token="star1" data-active="false" class='titanic titanic-star'></div>
  <div data-uniq-token="star2" data-active="false" class='titanic titanic-star'></div>
  <div data-uniq-token="star3" data-active="false" class='titanic titanic-star'></div>
  <div data-uniq-token="star4" data-active="false" class='titanic titanic-star'></div>
  <div data-uniq-token="star5" data-active="false" class='titanic titanic-star'></div>
</div>
.stars-container {
  display: flex;
}

.titanic-star {
  width : 50px;
  cursor : pointer;
  transition : all 0.2s;
  color  : #f47321;
}

.titanic-star path {
  fill : #f47321;
 stroke : #f47321;
  
}

.titanic-star[data-active="true"] path {
 }

.titanic-star:hover {
  transform : scale(1.1);
}
// eslint-disable-next-line no-unused-vars
var Titanic; // a global library container

//modified fork to run with uniqTokens

(function() {
  var startAnimationIndex = 0;
  var halfAnimationIndex = 13;
  var endAnimationIndex = 27;

  // --------- Titanic Item ---------- //
  function playOn() {
    this.anim.playSegments([startAnimationIndex, halfAnimationIndex], true);
    this.state = 1;
  }

  function playOff() {
    this.anim.playSegments([halfAnimationIndex + 1, endAnimationIndex], true);
    this.state = 0;
  }

  function playAll() {
    this.anim.playSegments([startAnimationIndex, endAnimationIndex], true);
    this.state = 0;
  }

  function toggle() {
    if (this.state === 0) {
      this.on();
    } else {
      this.off();
    }
  }

  var TitanicItem = function(element, token, options, baseURL) {
    var self = this;

    // props
    self.titanicToken = token;
    self.uniqToken = options.uniqToken;
    self.state = 0;
    // eslint-disable-next-line no-undef
    self.anim = bodymovin.loadAnimation({
      container: element,
      renderer: "svg",
      loop: false,
      autoplay: false,
      path: baseURL + token + ".json"
    });

    // methods
    self.on = playOn.bind(self);
    self.off = playOff.bind(self);
    self.play = playAll.bind(self);
    self.toggle = toggle.bind(self);

    if (options.click) {
      element.addEventListener("click", self.toggle);
    }
    if (options.hover) {
      element.addEventListener("pointerenter", self.toggle);
      element.addEventListener("pointerleave", self.toggle);
    }
  };

  // --------- Titanic Library ---------- //

  var titanicIcons = [];
  var isInitialized = false;

  function initialize(options, callback) {
    var baseURL = options.baseURL;

    document.addEventListener("DOMContentLoaded", function() {
      var titanicElements = document.getElementsByClassName("titanic");
      var i = titanicElements.length;

      while (i) {
        var element = titanicElements[--i];
        var match = element.className.match(/titanic-([^\s]+)/);
        options.uniqToken = element.dataset.uniqToken;

        if (match && match.length && match[1]) {
          titanicIcons.unshift(
            new TitanicItem(element, match[1], options, baseURL)
          );
        }
      }

      isInitialized = true;
      if (typeof callback === "function") {
        callback();
      }
    });
  }

  function findItem(token) {
    if (!isInitialized) {
      return;
    }
    for (var i = titanicIcons.length - 1; i >= 0; i--) {
      if (
        titanicIcons[i].titanicToken === token ||
        titanicIcons[i].uniqToken === token
      ) {
        return titanicIcons[i];
      }
    }
  }

  function applyMethod(itemToken, methodToken) {
    var titanicItem = findItem(itemToken);
    if (titanicItem && typeof titanicItem[methodToken] === "function") {
      titanicItem[methodToken]();
    }
  }

  Titanic = function(options) {
    this.options = {
      baseURL:
        options.baseURL ||
          "https://cdn.rawgit.com/icons8/titanic/master/dist/icons/",
      hover: options.hover !== undefined ? options.hover : true,
      click: options.click !== undefined ? options.click : false
    };

    var self = this;
    initialize(this.options, function() {
      self.items = titanicIcons;
      self.isInitialized = function() {
        return isInitialized;
      };
      self.on = function(token) {
        applyMethod(token, "on");
      };
      self.off = function(token) {
        applyMethod(token, "off");
      };
      self.play = function(token) {
        applyMethod(token, "play");
      };
    });
  };
})();

var titanic = new Titanic({
  hover: false, // auto animated on hover (default true)
  click: false // auto animated on click/tap (default false)
});










var StarRating = (function() {
  var self;
  var delay = 100;

  function getElementIndex(node) {
    var index = 0;
    while ((node = node.previousElementSibling)) {
      index++;
    }
    return index;
  }

  var starRating = function(params) {
    this.container = params.container;
    this.currentRate = params.rate || -1;

    self = this;

    this.bindStars();
  };

  starRating.prototype = {
    constructor: starRating,

    bindStars: function() {
      var stars = this.container.getElementsByClassName("titanic-star");
      var that = this;

      for (var i = 0, l = stars.length; i < l; ++i) {
        stars[i].addEventListener("click", that.rate, false);
      }

      this.stars = stars;
    },

    star: function(index) {
      return this.stars[index];
    },

    applyOnRange: function(start, end, func) {
      if (func === "on") {
        for (var i = start; i <= end; i++) {
          self.changeState(i, func);
        }
      } else {
        var i = end;
        var reverseIndex = 0;
        while (i >= start) {
          self.changeState(i, func, reverseIndex);
          --i;
          ++reverseIndex;
        }
      }
    },

    changeState: function(index, func, reverseIndex) {
      var star = this.stars[index];
      var uniqToken = star.dataset.uniqToken;

      var indexDelay = typeof reverseIndex !== "undefined"
        ? reverseIndex
        : index;

      setTimeout(
        function(index, uniqToken, star) {
          titanic[func](uniqToken);
          star.dataset.active = func === "on" ? "true" : "false";
        }.bind(null, index, uniqToken, star),
        indexDelay * delay
      );
    },

    rate: function() {
      //get el from event listner
      var el = this;
      var index = getElementIndex(el);
      var func;

      if (index > self.currentRate) {
        var padd = self.currentRate >= -1 ? 1 : 0;
        var indexPadd = 0;
        //on passe en on tt depuis last index jusqu'a new index
        self.applyOnRange(self.currentRate + padd, index, "on");
      } else if (index < self.currentRate) {
        self.applyOnRange(index, self.currentRate, "off");
        indexPadd = -1;
      } else if (index === self.currentRate) {
        //on fait juste un toggle
        if (el.dataset.active === "true") {
          self.applyOnRange(index, self.currentRate, "off");
          indexPadd = -1;
        } else {
          self.applyOnRange(index, self.currentRate, "on");
          this.currentRate = index;
        }
      }

      self.currentRate = index + indexPadd;
    },

    getRate: function() {
      return this.currentRate + 1;
    }
  };

  return starRating;
})();

new StarRating({ container: document.getElementById("stars-container") });

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/bodymovin/4.5.9/bodymovin.min.js