我爱编程程序员

JavaScript实现简单的按键评星效果

2018-05-19  本文已影响7人  立正小歪牙

最近有个项目需要在页面上通过点亮星星的形式显示一个评分结果:

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键的码值与字母键盘是不一致的,下面函数我用的是字母键盘中的数字键码值。

字母键盘键码值keyCode对应表 图片来源:百度经验 数字键盘键码值keyCode对应表 图片来源:百度经验
//键盘执行函数
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的样式并未清除,如下图:

clearStyle函数中console位置

console输出如下:

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还没有解决思路,如有大神指点感激不尽! (๑•̀ㅂ•́)و✧

上一篇下一篇

猜你喜欢

热点阅读