Перетворіть номер у відображення зірки, використовуючи jQuery та CSS


101

Я дивився на плагін jquery і цікавився, як адаптувати цей плагін, щоб перетворити число (наприклад, 4.8618164) у зірки 4.8618164, заповнені 5. Здебільшого інтерпретуючи число <5 на зірки, заповнені в 5-зірковій системі оцінювання за допомогою jQuery / JS / CSS.

Зауважте, що це відображатиме / показуватиме лише рейтинг зірок із уже наявного числа та не приймає нові подання рейтингів.


Відповіді:


255

Ось вам рішення, використовуючи лише одне дуже крихітне і просте зображення та один автоматично генерований прольотний елемент:

CSS

span.stars, span.stars span {
    display: block;
    background: url(stars.png) 0 -16px repeat-x;
    width: 80px;
    height: 16px;
}

span.stars span {
    background-position: 0 0;
}

Зображення

alt текст
(джерело: ulmanen.fi )

Примітка: робити НЕ хотлінк до зображення! Скопіюйте файл на власний сервер і використовуйте його звідти.

jQuery

$.fn.stars = function() {
    return $(this).each(function() {
        // Get the value
        var val = parseFloat($(this).html());
        // Make sure that the value is in 0 - 5 range, multiply to get width
        var size = Math.max(0, (Math.min(5, val))) * 16;
        // Create stars holder
        var $span = $('<span />').width(size);
        // Replace the numerical value with stars
        $(this).html($span);
    });
}

Якщо ви хочете обмежити зірки лише розмірами половини чи чверті, додайте один із цих рядків перед var sizeрядком:

val = Math.round(val * 4) / 4; /* To round to nearest quarter */
val = Math.round(val * 2) / 2; /* To round to nearest half */

HTML

<span class="stars">4.8618164</span>
<span class="stars">2.6545344</span>
<span class="stars">0.5355</span>
<span class="stars">8</span>

Використання

$(function() {
    $('span.stars').stars();
});

Вихід

Зображення з набору іконок фуги (www.pinvoke.com)
(джерело: ulmanen.fi )

Демо

http://www.ulmanen.fi/stuff/stars.php

Це, мабуть, відповідає вашим потребам. За допомогою цього методу вам не доведеться обчислювати жодних трьох чвертей чи не більше ширини зірки, просто дайте їй поплавок, і він дасть вам свої зірки.


Невелике пояснення того, як представлені зірки, може бути в порядку.

Сценарій створює два елементи блочного рівня. Обидва проміжки спочатку отримують розмір 80px * 16px та фонове зображення stars.png. Проміжки вкладені так, що структура прольотів виглядає так:

<span class="stars">
    <span></span>
</span>

Зовнішній проміжок отримує background-positionзначення 0 -16px. Це робить видимими сірі зірки у зовнішньому прольоті. Оскільки зовнішній проміжок має висоту 16 пікселів repeat-x, він показуватиме лише 5 сірих зірок.

Внутрішня оболонка з іншого боку , є background-positionз 0 0яких робить тільки жовті зірки видно.

Звичайно, це може працювати з двома окремими файлами зображень, star_yellow.png та star_gray.png. Але оскільки зірки мають фіксовану висоту, ми можемо легко поєднати їх в одне зображення. Для цього використовується техніка спрайту CSS .

Тепер, коли прольоти вкладені, вони автоматично накладаються один на одного. У випадку за замовчуванням, коли ширина обох прольотів становить 80 пікселів, жовті зірки повністю затемнюють сірі зірки.

Але коли ми регулюємо ширину внутрішнього прольоту, ширина жовтих зірок зменшується, виявляючи сірі зірки.

З text-indent: -9999pxточки зору доступності, було б розумніше залишити число поплавця всередині внутрішнього прольоту і заховати його , щоб люди з вимкненим CSS побачили принаймні номер плаваючої точки замість зірок.

Сподіваюся, це мало сенс.


Оновлено 22.10.2010

Тепер ще компактніше і важче зрозуміти! Можна також стиснути до одного вкладиша:

$.fn.stars = function() {
    return $(this).each(function() {
        $(this).html($('<span />').width(Math.max(0, (Math.min(5, parseFloat($(this).html())))) * 16));
    });
}

@Tatu, будь-який шанс розширити його трохи більше, як це працює. Мої знання про jQuery - це лише короткий термін, щоб повністю її отримати. Я думаю, я розумію, як CSS працює з повторенням у напрямку x і 16 * 5 = 80 біт і як ви регулюєте ширину жовто-зіркового зображення, але як ви накладаєте два зображення один на одного з a єдине зображення, яке має одну зірку вище іншої? Чи -16px приводить сіру зірку до такого ж рівня, як і жовту?
paxdiablo

Дякую за оновлення, @Tatu, що зараз має для мене набагато більше сенсу. На жаль, я вже дав вам +1, тому я не можу це зробити ще раз, але, сподіваємось, пояснення заробить вам більше (добре зароблений) представник. Ура.
paxdiablo

2
@paxdiablo та інші, дякую за підтримку. Можливо, я повинен зробити цей плагін правильним jQuery, оскільки ця методика для більшості здається несподіванкою :)
Tatu Ulmanen

@Tatu, величезне спасибі Існуючі п’ятизіркові плагіни, схоже, хочуть форми, яка чудово підходить для введення рейтингу, але є способом надмірності змінити представлення числа.
vfilby

7
Або навіть менше: jsbin.com/IBIDalEn/2/edit (PS видалено непотрібні речі в JS, мінімізовані селектори CSS та використані max-width).
Roko C. Buljan

30

Якщо вам потрібно підтримувати лише сучасні браузери, ви можете піти з:

  • Немає зображень;
  • Переважно статичний css;
  • Майже немає jQuery чи Javascript;

Вам потрібно лише перетворити число в a class, наприклад class='stars-score-50'.

Спочатку демонстрація розміченої "винесеної" розмітки

body { font-size: 18px; }

.stars-container {
  position: relative;
  display: inline-block;
  color: transparent;
}

.stars-container:before {
  position: absolute;
  top: 0;
  left: 0;
  content: '★★★★★';
  color: lightgray;
}

.stars-container:after {
  position: absolute;
  top: 0;
  left: 0;
  content: '★★★★★';
  color: gold;
  overflow: hidden;
}

.stars-0:after { width: 0%; }
.stars-10:after { width: 10%; }
.stars-20:after { width: 20%; }
.stars-30:after { width: 30%; }
.stars-40:after { width: 40%; }
.stars-50:after { width: 50%; }
.stars-60:after { width: 60%; }
.stars-70:after { width: 70%; }
.stars-80:after { width: 80%; }
.stars-90:after { width: 90%; }
.stars-100:after { width: 100; }
Within block level elements:

<div><span class="stars-container stars-0">★★★★★</span></div>
<div><span class="stars-container stars-10">★★★★★</span></div>
<div><span class="stars-container stars-20">★★★★★</span></div>
<div><span class="stars-container stars-30">★★★★★</span></div>
<div><span class="stars-container stars-40">★★★★★</span></div>
<div><span class="stars-container stars-50">★★★★★</span></div>
<div><span class="stars-container stars-60">★★★★★</span></div>
<div><span class="stars-container stars-70">★★★★★</span></div>
<div><span class="stars-container stars-80">★★★★★</span></div>
<div><span class="stars-container stars-90">★★★★★</span></div>
<div><span class="stars-container stars-100">★★★★★</span></div>

<p>Or use it in a sentence: <span class="stars-container stars-70">★★★★★</span> (cool, huh?).</p>

Потім демонстрація, яка використовує кодовий код:

$(function() {
  function addScore(score, $domElement) {
    $("<span class='stars-container'>")
      .addClass("stars-" + score.toString())
      .text("★★★★★")
      .appendTo($domElement);
  }

  addScore(70, $("#fixture"));
});
body { font-size: 18px; }

.stars-container {
  position: relative;
  display: inline-block;
  color: transparent;
}

.stars-container:before {
  position: absolute;
  top: 0;
  left: 0;
  content: '★★★★★';
  color: lightgray;
}

.stars-container:after {
  position: absolute;
  top: 0;
  left: 0;
  content: '★★★★★';
  color: gold;
  overflow: hidden;
}

.stars-0:after { width: 0%; }
.stars-10:after { width: 10%; }
.stars-20:after { width: 20%; }
.stars-30:after { width: 30%; }
.stars-40:after { width: 40%; }
.stars-50:after { width: 50%; }
.stars-60:after { width: 60%; }
.stars-70:after { width: 70%; }
.stars-80:after { width: 80%; }
.stars-90:after { width: 90%; }
.stars-100:after { width: 100; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Generated: <div id="fixture"></div>

Найбільші недоліки цього рішення:

  1. Вам потрібні зірки всередині елемента для створення правильної ширини;
  2. Немає семантичної розмітки, наприклад, ви б віддали перевагу балу як тексту всередині елемента;
  3. Він дозволяє отримати лише стільки балів, скільки у вас буде класів (тому що ми не можемо використовувати Javascript для точного widthвстановлення псевдоелемента).

Щоб виправити це, рішення вище можна легко підправити. :beforeІ :afterбіти повинні стати фактичними елементами в DOM (так що нам потрібно деякий JS для цього).

Останнє залишається читачем як вправа.


3
Я розширив це рішення для розміщення поплавків і динамічно генерованих балів, які не вкладаються в 10-ту частину 100. Codepen . Дякуємо за те, що я розпочав роботу: D
вийшов

Це досить милий сценарій
Нік Дів

1
Ідеальне рішення. Ти зробив мій день . Дякую @Jeroen ... продовжуй гойдатися.
Прабху Нандан Кумар

22

Спробуйте цю функцію / файл помічника jquery

jquery.Rating.js

//ES5
$.fn.stars = function() {
    return $(this).each(function() {
        var rating = $(this).data("rating");
        var fullStar = new Array(Math.floor(rating + 1)).join('<i class="fas fa-star"></i>');
        var halfStar = ((rating%1) !== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
        var noStar = new Array(Math.floor($(this).data("numStars") + 1 - rating)).join('<i class="far fa-star"></i>');
        $(this).html(fullStar + halfStar + noStar);
    });
}

//ES6
$.fn.stars = function() {
    return $(this).each(function() {
        const rating = $(this).data("rating");
        const numStars = $(this).data("numStars");
        const fullStar = '<i class="fas fa-star"></i>'.repeat(Math.floor(rating));
        const halfStar = (rating%1!== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
        const noStar = '<i class="far fa-star"></i>'.repeat(Math.floor(numStars-rating));
        $(this).html(`${fullStar}${halfStar}${noStar}`);
    });
}

index.html

   <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Star Rating</title>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script src="js/jquery.Rating.js"></script>
        <script>
            $(function(){
                $('.stars').stars();
            });
        </script>
    </head>
    <body>

        <span class="stars" data-rating="3.5" data-num-stars="5" ></span>

    </body>
    </html>

Знімок екрана


Лише зауважте, що тега </script> відсутній :)
Роб Стоцький

7

Чому б просто не було п’яти окремих зображень зірки (порожня, чверть, напівповна, три чверті і повна), а потім просто ввести зображення у свій DOM залежно від усіченого або розбитого значення рейтингу, помноженого на 4 ( щоб отримати цілий число за чверті)?

Наприклад, 4,88618164, помножене на 4 і округлене 19, це було б чотири і три чверті зірок.

Крім того, (якщо ви ліниві, як я), просто виберіть одне зображення з 21 (0 зірок до 5 зірок з кроком на одну чверть) та виберіть єдине зображення, виходячи з вищезазначеного значення. Тоді це лише один розрахунок з подальшим зміною зображення в DOM (а не спробою змінити п'ять різних зображень).


5

Я закінчився повністю без JS, щоб уникнути відставання від надання клієнта на стороні клієнта. Для цього я генерую такий HTML:

<span class="stars" title="{value as decimal}">
    <span style="width={value/5*100}%;"/>
</span>

Щоб допомогти у доступності, я навіть додаю необмежене рейтингове значення в атрибут title.


4

використовуючи jquery без прототипу, оновіть код js до

$( ".stars" ).each(function() { 
    // Get the value
    var val = $(this).data("rating");
    // Make sure that the value is in 0 - 5 range, multiply to get width
    var size = Math.max(0, (Math.min(5, val))) * 16;
    // Create stars holder
    var $span = $('<span />').width(size);
    // Replace the numerical value with stars
    $(this).html($span);
});

Я також додав атрибут даних за назвою рейтинг даних у проміжку.

<span class="stars" data-rating="4" ></span>

2

DEMO

Ви можете зробити це лише з 2-х зображень. 1 порожні зірки, 1 заповнені зірки.

Накладене зображення накладене зверху на інше. і конвертувати рейтинговий номер у відсоток і використовувати його як ширину зображення наповнювача.

введіть тут опис зображення

.containerdiv {
  border: 0;
  float: left;
  position: relative;
  width: 300px;
} 
.cornerimage {
  border: 0;
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
 } 
 img{
   max-width: 300px;
 }

0

Ось мій прийом із використанням JSX та шрифтів дивовижний, обмежений лише точністю .5, хоча:

       <span>
          {Array(Math.floor(rating)).fill(<i className="fa fa-star"></i>)}
          {(rating) - Math.floor(rating)==0 ? ('') : (<i className="fa fa-star-half"></i>)}
       </span>

Перший ряд - для цілої зірки, а другий - для півзірки (якщо такий є)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.