使用jQuery和CSS将数字转换为星级显示


101

我一直在研究jquery插件,想知道如何修改该插件以将一个数字(如4.8618164)转换为4.8618164个星(填充5个星)。基本上使用jQuery将数字<5解释为一个5星评级系统中的星/ JS / CSS。

请注意,这只会显示/显示现有数字中的星级,而不接受新的评级提交。


Answers:


255

这是为您提供的解决方案,仅使用一个非常小而简单的图像和一个自动生成的span元素:

的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;
}

图片

替代文字
(来源: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,并且背景图片为star.png。跨度是嵌套的,因此跨度的结构如下所示:

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

外部跨度background-position0 -16px。这样就可以看到外部跨度中的灰色星星。由于外部跨度的高度为16px和repeat-x,它将仅显示5个灰色星体。

在另一方面内宽度具有background-position0 0,这使得只有黄色星星可见。

这当然可以使用两个单独的图像文件star_yellow.png和star_gray.png。但是由于恒星具有固定的高度,因此我们可以轻松地将它们合并为一张图像。这利用了CSS Sprite技术

现在,由于跨度是嵌套的,因此它们将自动彼此重叠。在默认情况下,当两个跨度的宽度均为80px时,黄色星星会完全遮盖灰色星星。

但是,当我们调整内部跨度的宽度时,黄色星星的宽度会减小,从而露出灰色星星。

在可访问性方面,将浮点数保留在内部跨度中并用隐藏是比较明智​​的选择text-indent: -9999px,这样,关闭CSS的人至少会看到浮点数而不是星号。

希望这是有道理的。


更新于2010/10/22

现在变得更加紧凑和难以理解!也可以压成一个衬板:

$.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位重复播放,以及如何调整黄星图像的宽度,但是如何将两个图像彼此重叠一颗星比另一颗星高的单一图像?-16px是否会使灰色的星星与黄色的星星处于同一水平?
paxdiablo'1

感谢@Tatu的更新,这对我而言现在变得更加有意义。不幸的是,我已经给您+1了,所以我不能再做一次了,但希望您的解释会为您赢得更多(来之不易)代表。干杯。
paxdiablo'1

2
@paxdiablo和其他人,感谢您的支持。也许我应该使它成为一个合适的jQuery插件,因为这种技术似乎使大多数人惊讶:)
Tatu Ulmanen 2010年

@Tatu,非常感谢。现有的五星级插件似乎都希望使用一种适合输入等级的表格,但是要改变数字的表示却过于刻板。
vfilby

7
甚至更小: jsbin.com/IBIDalEn/2/edit(PS删除了JS中不需要的东西,缩小了CSS选择器并使用了max-width)。
Roko C. Buljan 2013年

30

如果只需要支持现代浏览器,则可以摆脱:

  • 没有图像;
  • 主要是静态CSS;
  • 几乎没有jQuery或Javascript;

您只需要将数字转换为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
我扩展了此解决方案,以适应浮点数和动态生成的分数(不适用于100的十分之一)。Codepen。谢谢您开始使用:D
cameck

这是一个非常不错的脚本
Nick Div '18

1
完美的解决方案。你让我今天一整天都感觉很好 。谢谢@杰罗恩...继续摇摆。
Prabhu Nandan Kumar

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>标记:)
Rob Stocki

7

为什么不只拥有五张单独的恒星图像(空,四分之一满,半满,四分之三满和满),然后根据截断或成行的等级值乘以4(得到整个季度的数字)?

例如,4.8618164乘以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);
});

我还通过跨度中的data-rating名称添加了data属性。

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

2

演示

您只能使用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>

第一排代表整颗星,第二排代表半颗星(如果有)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.