Задать вопрос
@prokopn

Как реализовать звёздный рейтинг с закрашиванием звёзд?

Как сделать звездный рейтинг так, чтобы звезды можно было закрашивать при наведении и клике? Сейчас только через input работает.

<div class="rating  rating_set">
  <div class="rating__body">
    <div class="rating__line"></div>
    <div class="rating__activeline"></div>
    <div class="rating__stars">
      <input type="radio" class="rating__star" value="1" name="rating" />
      <input type="radio" class="rating__star" value="2" name="rating" />
      <input type="radio" class="rating__star" value="3" name="rating" />
      <input type="radio" class="rating__star" value="4" name="rating" />
      <input type="radio" class="rating__star" value="5" name="rating" />
    </div>
    <input value="5" type="text" name="rating" class="rating-input" />
  </div>
</div>

.rating {
  display: flex;
  flex-wrap: wrap;
}
.rating__body {
  display: inline-block;
  position: relative;
  width: 192px;
  height: 32px;
}
.rating__body .rating-input {
  display: none;
  padding: 11px;
}
.rating__line {
  position: absolute;
  width: 192px;
  height: 32px;
  top: 0;
  left: 0;
  z-index: 1;
  background: url("https://habrastorage.org/webt/8t/4a/k5/8t4ak5vv6tweelwxgccbyb0mpm0.png") 0 0 no-repeat;
	background-size: 100% 100%;
}
.rating__activeline {
  position: absolute;
  height: 32px;
  top: 0;
  left: 0;
  background: url("https://habrastorage.org/webt/yr/ct/s0/yrcts0ipk6fzpfnoe7_aobbkxmq.png") 0 0 no-repeat;
  z-index: 2;
}
.rating__stars {
  width: 100%;
  display: flex;
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}
.rating__star {
  flex: 0 0 20%;
  height: 100%;
  opacity: 0;
}

const ratings = document.querySelectorAll(".rating")
if (ratings.length > 0) {
  initRatings()
}
// Основная функция
function initRatings() {
  let ratingActive, ratingValue
  // "Бегаем" по всем рейтингам на странице
  for (let index = 0; index < ratings.length; index++) {
    const rating = ratings[index]
    initRating(rating)
  }
  // Инициализируем конкретный рейтинг
  function initRating(rating) {
    initRatingVars(rating)

    setRatingActiveWidth()

    if (rating.classList.contains("rating_set")) {
      setRating(rating)
    }
  }
  // Инициализайция переменных
  function initRatingVars(rating) {
    ratingActive = rating.querySelector(".rating__activeline")
    ratingValue = rating.querySelector(".rating-input")
  }
  // Изменяем ширину активных звезд
  function setRatingActiveWidth() {
    const ratingActiveWidth = ratingValue.value / 0.05
    ratingActive.style.width = `${ratingActiveWidth}%`
  }

  ratingValue.addEventListener("change", function () {
    setRatingActiveWidth()
  })

  // Возможность указать оценку
  function setRating(rating) {
    const ratingItems = rating.querySelectorAll(".rating__star")
    for (let index = 0; index < ratingItems.length; index++) {
      const ratingItem = ratingItems[index]
      ratingItem.addEventListener("mouseenter", function (e) {
        // Обновление переменных
        initRatingVars(rating)
        // Обновление активных звезд
        setRatingActiveWidth(ratingItem.value)
      })
      ratingItem.addEventListener("mouseleave", function (e) {
        // Обновление активных звезд
        setRatingActiveWidth()
      })
      ratingItem.addEventListener("click", function (e) {
        // Обновление переменных
        initRatingVars(rating)

        if (rating.dataset.ajax) {
          // "Отправить" на сервер
          setRatingValue(ratingItem.value, rating)
        } else {
          // Отобразить указанную оцнку
          ratingValue.value = index + 1
          setRatingActiveWidth()
        }
      })
    }
  }
}
  • Вопрос задан
  • 72 просмотра
Подписаться 1 Средний 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы