jQueryとCSSを使用して、数値を星評価表示に変える


101

私はjqueryプラグインを見ていて、そのプラグインを適用して、数値(4.8618164など)を5で満たされた4.8618164の星に変換する方法を考えていました。 / JS / CSS。

これは、すでに利用可能な番号からの星の評価のみを表示/表示し、新しい評価の提出を受け入れないことに注意してください。


回答:


255

非常に小さくシンプルな画像を1つと、自動的に生成されたスパン要素を1つだけ使用するソリューションを次に示します。

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

星のサイズを半分または4分の1に制限する場合は、次の行のいずれかを行の前に追加します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

これはおそらくあなたのニーズに合うでしょう。この方法を使用すると、4分の3や星の幅を計算する必要はありません。浮動小数点数を指定するだけで、星が得られます。


星がどのように提示されるかについての簡単な説明が適切かもしれません。

スクリプトは、2つのブロックレベルのスパン要素を作成します。両方のスパンは、最初に80px * 16pxのサイズと背景画像stars.pngを取得します。スパンはネストされているため、スパンの構造は次のようになります。

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

外側のスパンはのbackground-positionを取得し0 -16pxます。これにより、外側のスパンの灰色の星が見えるようになります。外側のスパンの高さは16pxとなので、repeat-x灰色の星は5つしか表示されません。

一方、内側のスパンにはbackground-position0 0あり、黄色の星だけが表示されます。

もちろん、これはstar_yellow.pngとstar_gray.pngの2つの別々の画像ファイルで機能します。ただし、星の高さは固定されているため、簡単に1つの画像にまとめることができます。これはCSSスプライト技術を利用しています。

これで、スパンがネストされるため、スパンは自動的に互いにオーバーレイされます。デフォルトの場合、両方のスパンの幅が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ビットでどのように機能するか、そして黄色の星の画像の幅をどのように調整するかを理解していると思いますが、2つの画像を1つの星が他の星の上にある単一の画像?-16pxは灰色の星を黄色と同じレベルに引き上げますか?
paxdiablo

更新してくれてありがとう、@ Tatu。残念ながら、私はすでに+1をしているので、二度とそれを行うことはできませんが、うまくいけば、この説明で(熟練した)担当者がさらに増えることを期待しています。乾杯。
paxdiablo

2
@paxdiabloなど、サポートに感謝します。おそらく私はこれを適切なjQueryプラグインにする必要があります。この手法はほとんどの人にとって驚きと思われるからです。)
Tatu Ulmanen

@Tatu、本当にありがとう。既存の5つ星のプラグインはすべて、評価の入力には問題ないが、数値の表現を変更するのはやり過ぎなフォームを必要としているようです。
vfilby 2010

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の10分の1に収まらない動的に生成されたスコアに対応しました。始めてくれてありがとう:D
cameck

これはかなり甘いスクリプトです
Nick Div

1
完璧なソリューション。あなたは私の日を作りました。@Jeroenに感謝します。
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 2017

7

星の5つの個別の画像(空、1/4フル、ハーフフル、3/4フル、フル)を用意せず、評価の切り捨てまたはルート化された値に4を掛けて、DOMに画像を挿入するだけです(四半期全体で数字を取得するために)?

たとえば、4.8618164に4を掛けて四捨五入すると19になり、4つ星と3つ星になります。

または(私のように怠惰な場合)、21から1つの画像(0から5つ星の4分の1の増分)を選択し、前述の値に基づいて単一の画像を選択します。次に、(5つの異なる画像を変更しようとするのではなく)DOM内の画像の変更が続く1つの計算です。


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

デモ

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とfont awesomeを使用した私の見解は次のとおりです。

       <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>

最初の行は星全体、2番目の行は半分星(ある場合)です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.