JQuery ve CSS kullanarak bir sayıyı yıldız derecelendirme ekranına dönüştürün


101

Jquery eklentisine bakıyordum ve bu eklentiyi bir sayıyı (4.8618164 gibi) 5 üzerinden doldurulmuş 4.8618164 yıldıza dönüştürmek için nasıl uyarlayacağımı merak ediyordum. / JS / CSS.

Bunun yalnızca halihazırda mevcut bir numaradan yıldız derecelendirmesini görüntüleyeceğini / göstereceğini ve yeni derecelendirme gönderilerini kabul etmediğini unutmayın.


Yanıtlar:


256

İşte size çok küçük ve basit bir görüntü ve otomatik olarak oluşturulmuş bir yayılma öğesi kullanan bir çözüm:

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

Resim

alternatif metin
(kaynak: ulmanen.fi )

Not: do DEĞİL yukarıdaki resimde sıcak bağlantı! Dosyayı kendi sunucunuza kopyalayın ve oradan kullanın.

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

Yıldızları yalnızca yarım veya çeyrek yıldız boyutlarıyla sınırlamak istiyorsanız, şu satırlardan birini satırın önüne ekleyin 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>

Kullanım

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

Çıktı

Füg simge setinden görüntü (www.pinvoke.com)
(kaynak: ulmanen.fi )

Demo

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

Bu muhtemelen ihtiyaçlarınızı karşılayacaktır. Bu yöntemle, herhangi bir üç çeyrek veya yıldız genişliğini hesaplamanıza gerek kalmaz, sadece bir şamandıra verin ve size yıldızlarınızı verecektir.


Yıldızların nasıl sunulduğuna dair küçük bir açıklama sırayla olabilir.

Komut dosyası, iki blok düzeyinde yayılma öğesi oluşturur. Her iki aralık da başlangıçta 80px * 16px boyutunda ve bir arka plan görüntüsü stars.png alır. Açıklıklar iç içe geçmiştir, böylece açıklıkların yapısı aşağıdaki gibi görünür:

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

Dış açıklık bir background-position/ alır 0 -16px. Bu, dış açıklıktaki gri yıldızları görünür kılar. Dış açıklığın yüksekliği 16 piksel olduğundan ve repeat-xyalnızca 5 gri yıldız gösterecektir.

Diğer taraftan, iç açıklık bir yer alır background-positionve 0 0burada sadece sarı yıldız görünür hale getirir.

Bu elbette iki ayrı resim dosyasıyla, star_yellow.png ve star_gray.png ile çalışır. Ancak yıldızlar sabit bir yüksekliğe sahip olduğundan, onları kolayca tek bir görüntüde birleştirebiliriz. Bu, CSS sprite tekniğini kullanır .

Şimdi, aralıklar iç içe geçtikçe, otomatik olarak birbirlerinin üzerine yerleştirilirler. Varsayılan durumda, her iki aralığın genişliği 80 piksel olduğunda, sarı yıldızlar gri yıldızları tamamen gizler.

Ancak iç açıklığın genişliğini ayarladığımızda, sarı yıldızların genişliği azalır ve gri yıldızları ortaya çıkarır.

Erişilebilirlik açısından, şamandıra numarasını iç yayılma alanının içinde bırakmak ve bununla gizlemek daha akıllıca olurdu text-indent: -9999px, böylece CSS kapalı olan insanlar, yıldızlar yerine en azından kayan nokta sayısını görebilirlerdi.

Umarım bu biraz mantıklıydı.


2010/10/22 güncellendi

Şimdi daha da kompakt ve anlaşılması daha zor! Ayrıca tek bir astara kadar sıkıştırılabilir:

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

@Tatu, bunun nasıl çalıştığıyla ilgili olarak onu biraz daha ortaya çıkarma şansı . JQuery hakkındaki bilgim tamamen anlamak için biraz kısa. CSS'nin x yönünde ve 16 * 5 = 80 bit yinelemeyle nasıl çalıştığını ve sarı yıldız görüntüsünün genişliğini nasıl ayarladığınızı anladığımı düşünüyorum, ancak iki görüntüyü bir diğerinin üzerinde yıldız olan tek görüntü? -16px, gri yıldızı sarı ile aynı seviyeye getirir mi?
paxdiablo

Güncelleme için teşekkürler, @Tatu, bu artık benim için çok daha anlamlı. Maalesef size +1 vermiştim, bu yüzden tekrar yapamam ama umarım açıklama size biraz daha (hak edilmiş) temsilci kazandırır. Şerefe.
paxdiablo

2
@paxdiablo ve diğerleri, desteğiniz için teşekkürler. Belki de bunu uygun bir jQuery eklentisi yapmalıyım, çünkü bu teknik çoğu kişiye sürpriz gibi geliyor :)
Tatu Ulmanen

@Tatu, çok teşekkürler. Mevcut beş yıldızlı eklentilerin tümü, bir derecelendirme girmek için uygun, ancak bir sayının temsilini değiştirmek için fazlasıyla abartılı bir form istiyor gibi görünüyor.
vfilby

7
Veya daha da küçük: jsbin.com/IBIDalEn/2/edit (PS, JS'deki gereksiz şeyleri kaldırdı, küçültülmüş CSS seçicileri ve kullanıldı max-width).
Roko C. Buljan

30

Yalnızca modern tarayıcıları desteklemeniz gerekiyorsa, şunlardan kurtulabilirsiniz:

  • Görüntü yok ;
  • Çoğunlukla statik css;
  • Neredeyse hiç jQuery veya Javascript;

Yalnızca sayıyı a'ya dönüştürmeniz gerekir class, örn class='stars-score-50'.

İlk olarak "oluşturulmuş" işaretlemenin bir demosu:

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>

Daha sonra küçük bir kod parçası kullanan bir demo:

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

Bu çözümün en büyük dezavantajları:

  1. Doğru genişliği oluşturmak için elementin içindeki yıldızlara ihtiyacınız var;
  2. Anlamsal bir işaretleme yoktur, örneğin puanı öğenin içinde metin olarak tercih edersiniz ;
  3. Birçok puanları gibi sınıfları gerekecek gibi için (biz çünkü sadece verir olamaz kesin ayarlamak için Javascript kullanmak widthbir sözde elemanı üzerine).

Bunu düzeltmek için yukarıdaki çözüm kolayca değiştirilebilir. :beforeVe :afterbit (biz bunun için bazı JS ihtiyaç böylece) DOM gerçek unsurlar haline gerekir.

İkincisi, okuyucu için bir egzersiz olarak bırakılmıştır.


3
Bu çözümü, 100'ün 10'una uymayan kayan sayılar ve dinamik olarak oluşturulmuş puanlar için genişlettim . Codepen .
Başlamamı sağladığınız

Bu oldukça tatlı bir senaryo
Nick Div

1
Mükemmel çözüm. Günümü gün ettin . Teşekkürler @Jeroen ... sallamaya devam edin.
Prabhu Nandan Kumar

22

Bu jquery yardımcı işlevini / dosyasını deneyin

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>

Ekran görüntüsü


Kapanış </script> etiketinin eksik olduğuna dikkat edin :)
Rob Stocki

7

Neden bir yıldızın beş ayrı görüntüsüne sahip olmuyorsunuz (boş, çeyrek dolu, yarı dolu, üçte üçü dolu ve dolu), ardından 4 ile çarpılan derecelendirmenin kesilmiş veya yuvarlatılmış değerine bağlı olarak görüntüleri DOM'nize enjekte etmiyorsunuz ( çeyrekler için tam bir rakam elde etmek için)?

Örneğin, 4.8618164 4 ile çarpılır ve yuvarlanır 19'dur, bu da dört ve üç çeyrek yıldız olur.

Alternatif olarak (benim gibi tembelseniz), 21 (0 yıldızdan 5 yıldıza çeyreklik artışlarla) arasından bir görüntü seçin ve yukarıda belirtilen değere göre tek görüntüyü seçin. O zaman sadece bir hesaplama ve ardından DOM'da bir resim değişikliği (beş farklı resmi değiştirmeye çalışmak yerine).


5

İstemci tarafında oluşturma gecikmesini önlemek için tamamen JS'siz hale geldim. Bunu başarmak için şu şekilde HTML oluşturuyorum:

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

Erişilebilirliğe yardımcı olmak için, başlık özelliğine ham derecelendirme değerini bile ekliyorum.


4

prototip olmadan jquery kullanarak, js kodunu güncelleyin

$( ".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);
});

Ayrıca aralıkta veri derecelendirme adına göre bir veri özelliği ekledim.

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

3

DEMO

Bunu sadece 2 resimle yapabilirsiniz. 1 boş yıldız, 1 dolu yıldız.

Diğerinin üstüne doldurulmuş görüntüyü yerleştirin. ve derecelendirme numarasını yüzdeye dönüştürür ve bunu dolgu görüntüsünün genişliği olarak kullanır.

görüntü açıklamasını buraya girin

.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

İşte JSX ve harika yazı tipini kullanmam, sadece .5 doğrulukla sınırlı olsa da:

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

İlk sıra tüm yıldız içindir ve ikinci sıra yarım yıldız içindir (varsa)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.