我一直在看 jquery 插件,想知道如何调整该插件以将数字(如 4.8618164)转换为 4.8618164 颗星,满分为 5。基本上使用 jQuery 将<5 的数字解释为 5 星评级系统中的星/JS/CSS。
请注意,这只会显示/显示现有数字中的星级评分,并且不接受新的评分提交。
我一直在看 jquery 插件,想知道如何调整该插件以将数字(如 4.8618164)转换为 4.8618164 颗星,满分为 5。基本上使用 jQuery 将<5 的数字解释为 5 星评级系统中的星/JS/CSS。
请注意,这只会显示/显示现有数字中的星级评分,并且不接受新的评分提交。
这是一个适合您的解决方案,仅使用一个非常小而简单的图像和一个自动生成的 span 元素:
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)
注意:千万不要热链接上面的图像!将文件复制到您自己的服务器并从那里使用它。
$.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 */
<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();
});
(来源:ulmanen.fi)
这可能会满足您的需求。使用这种方法,您不必计算任何四分之三或诸如此类的星形宽度,只需给它一个浮点数,它就会为您提供星星。
关于星星如何呈现的一个小解释可能是有序的。
该脚本创建了两个块级跨度元素。两个跨度最初都获得 80px * 16px 的大小和一个背景图像 stars.png。跨度是嵌套的,因此跨度的结构如下所示:
<span class="stars">
<span></span>
</span>
外跨度得到了background-position
的0 -16px
。这使得外跨度中的灰色星星可见。由于外跨度的高度为 16px 和repeat-x
,因此它只会显示 5 颗灰色星星。
另一方面,内跨度有一个background-position
,0 0
其中只有黄色的星星可见。
这当然适用于两个单独的图像文件,star_yellow.png 和 star_gray.png。但是由于星星的高度是固定的,我们可以很容易地将它们组合成一个图像。这利用了CSS 精灵技术。
现在,由于跨度是嵌套的,它们会自动相互重叠。默认情况下,当两个跨度的宽度都是 80px 时,黄色的星星完全遮住了灰色的星星。
但是当我们调整内跨的宽度时,黄色星星的宽度变小,露出灰色星星。
在可访问性方面,将浮点数留在内部跨度内并用 隐藏它会更明智text-indent: -9999px
,这样关闭 CSS 的人至少会看到浮点数而不是星星。
希望这是有道理的。
现在更紧凑,更难理解!也可以压缩成单层:
$.fn.stars = function() {
return $(this).each(function() {
$(this).html($('<span />').width(Math.max(0, (Math.min(5, parseFloat($(this).html())))) * 16));
});
}
如果您只需要支持现代浏览器,您可以使用:
您只需要将数字转换为 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>
这种解决方案的最大缺点是:
width
伪元素进行精确设置)。要解决此问题,可以轻松调整上述解决方案。在:before
与:after
位需要成为DOM实际元素(所以我们需要一些JS为)。
后者留给读者作为练习。
试试这个 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}`);
});
}
索引.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>
为什么不只有五个单独的星星图像(空的、四分之一满的、半满的、四分之三的和满的)然后根据截断或粗略的评级值乘以 4(获得四分之一的整数)?
例如,4.8618164 乘以 4 并四舍五入是 19,这将是四分之三星。
或者(如果你像我一样懒惰),只需从 21 个图像(0 星到 5 星,以四分之一为增量)中选择一个图像,然后根据上述值选择单个图像。然后它只是一个计算,然后在 DOM 中更改图像(而不是尝试更改五个不同的图像)。
我最终完全不使用 JS 以避免客户端渲染延迟。为了实现这一点,我生成了这样的 HTML:
<span class="stars" title="{value as decimal}">
<span style="width={value/5*100}%;"/>
</span>
为了提高可访问性,我什至在 title 属性中添加了原始评分值。