最近有个项目需要在页面上通过点亮星星的形式显示一个评分结果:
1、适合对多个对象进行评分
2、需要展示分数从0开始每颗星星点亮的变化
刚开始找到一个starability.css纯css插件,这个插件可以实现点击星星实现星星点亮的酷炫的动画效果。
插件地址:starability
但是项目要求不能通过鼠标直接点击星星来点亮,还需要展示每颗星星点亮的过程,所以我打算通过url参数来控制对象和预设分数,通过点击页面上的显示结果按钮,评分展示出来,需要借助JavaScript。
演示地址:JavaScript按钮评分效果demo
html结构
我选择了插件中星星向上滚动的效果starability-slot,html结构如下:
<div class="starability-container">
<h1>标题</h1>
<form>
<fieldset class="starability-slot" id="slot">
<input type="radio" id="rate1-2" name="rating" value="1" />
<label for="rate1-2" title="Terrible">1 stars</label>
<input type="radio" id="rate2-2" name="rating" value="2" />
<label for="rate2-2" title="Not good">2 stars</label>
<input type="radio" id="rate3-2" name="rating" value="3" />
<label for="rate3-2" title="Average">3 stars</label>
<input type="radio" id="rate4-2" name="rating" value="4" />
<label for="rate4-2" title="Very good">4 stars</label>
<input type="radio" id="rate5-2" name="rating" value="5" />
<label for="rate5-2" title="Amazing">5 star</label>
</fieldset>
</form>
</div>
<a class="btn" id="btn">显示结果</a>
获取url参数
要获取url参数www.xxxx.com?tit=标题&score=5中的tit和score值,需要用到getUrlParam函数。
一般我们用到getUrlParam函数的时候最后一行一般是return unescape(results[1]);,但是因为我需要从url获取中文参数,这样会导致乱码,因此改用decodeURI解码。
function getUrlParam(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if (results == null)
return "";
else
return decodeURI(results[1]);//浏览器会将url中的中文参数进行encodeURI编码,所以要通过js使用decodeURI进行解码,return unescape(results[1]);适合gb2312
}
定义两个全局变量:
var tit = getUrlParam("tit");//标题
var score = getUrlParam("score");//星星数:1-5分
点亮星星
使用setTimeout函数控制每颗星星点亮的间隔时间,每隔0.5s调用一次starlight函数,直到到达设定分数。
var i = 0;
var t;
function starlight() {
if (score > 5) score = 5;
if (score < 1) score = 1;
if (i < score) {
var slot = document.getElementById("slot");
var stars = slot.getElementsByTagName("input");
var labels = slot.getElementsByTagName("label");
var styleStr = "background-position: 0 -240px;transition: background-position .7s;";//240px为星星图片宽度
stars[i].setAttribute("style", styleStr);
labels[i].setAttribute("style", styleStr);
t = setTimeout(starlight, 500);
i++;
}
}
打开页面就要显示设定好的标题,点亮星星是通过点击按钮后才显示。
//获取标题
function getTit(tit) {
if (tit == "") {
alert("请填写tit值");
return false;
}
var h1 = document.getElementsByTagName("h1");
h1[0].innerHTML = tit;
}
window.onload=getTit(tit);
//点击按钮调用 starlight函数
document.getElementById("btn").addEventListener("click", function () {
starlight();
});
一个简单的评星效果就实现了。
项目优化
由于需要每次更改url参数score的值,必须预先设定好分数,操作起来不太方便。
改用键盘数字1-5键控制星星点亮数,其他键清空。
演示地址:JavaScript按键评分效果demo
完整代码:下载地址
清除样式函数
由于clearStyle和starlight函数都需要引用stars、labels,需要把stars、labels改为全局变量。
var slot = document.getElementById("slot");
var stars = slot.getElementsByTagName("input");
var labels = slot.getElementsByTagName("label");
clearStyle函数如下:
function clearStyle() {
i = 0;
for (j = 0; j < stars.length; j++) {
stars[j].removeAttribute("style");
labels[j].removeAttribute("style");
}
}
starlight函数可以简化如下:
function starlight() {
if (score > labels.length) score = labels.length;
if (score < 0) score = 0;
if (i < score) {
var styleStr = "background-position: 0 -240px;transition: background-position .5s;";//240px为星星图片宽度
stars[i].setAttribute("style", styleStr);
labels[i].setAttribute("style", styleStr);
t = setTimeout(starlight, 500);
i++;
}
}
按键执行函数
把之前click侦听按钮函数改为onkeydown函数,switch函数对应键值事件。
需要注意的是,数字键盘中的1-5键的码值与字母键盘是不一致的,下面函数我用的是字母键盘中的数字键码值。
//键盘执行函数
document.onkeydown = function (event) {
var e = event || window.event || arguments.callee.caller.arguments[0];
var keyNum = e && e.keyCode;
switch (keyNum) {
case 49://键盘数字键1
score = 1;
break;
case 50://键盘数字键2
score = 2;
break;
case 51://键盘数字键3
score = 3;
break;
case 52://键盘数字键4
score = 4;
break;
case 53://键盘数字键5
score = 5;
break;
default:
score = 0;
break;
}
clearStyle();
starlight();
}
改写后的页面可以不用刷新就能控制分数了。
遇到的问题
优化过后的代码遇到一个小bug,按下1到5键过后,如果继续按下1-5其中一个键,第一个input和label的样式并未清除,如下图:
console输出如下:
1、我在页面一开始调用了一个consloe.log(stars[0]),确认初始状态第一个input并未有style;
2、为按下5键的状态,可以看到clearStyle函数中star[0]即第一个input中的style并未被清除,但是2-5的input中的style已被清除;
3、为接着按下2键的状态,第一个input中的style依然并未被清除;
4、为再接着按下其他键的状态,第一个input中的style被清除了。
目前这个bug还没有解决思路,如有大神指点感激不尽! (๑•̀ㅂ•́)و✧