js 实现评分组件

2020/12/12 功能实现 共 2863 字,约 9 分钟

背景

亲,记得给给五星好评哟,网购or点外卖的时候,是不是经常听到这句话。用户的满意度评价是一个很常见的需求,不知道你是否自己动手实现过还是直接网上copy代码or插件框架套用。如何动手实现他?是否可以不借助js实现呢?

需求描述

  1. 鼠标在其上移动,评分变更

  2. 点击评分后,固定评分

  3. 鼠标离开后,回显上次评分

实现思路

  1. 每个星星都是可以点击的,星星数量不一定 => 借助 css 变量,实现一个标签包裹多个星星
 <star style="--level:6"></star>
  1. 鼠标移动or点击的时候,当前星星高亮,其余不变 => 借助另一个 css 变量,只展示高亮星星
e.target.style.setProperty('--value', starValue)
  1. 鼠标移动上去的高亮到当前的星星 =>

a.记录局部当前移动到第几个星星和当前星星的位置;

b.前面的星星都高亮,根据当前星星的位置判断是半个还是一颗

  this.params.eleBox.addEventListener("mousemove",function(e){
      _that.starLight(e.offsetX)
  })
  1. 鼠标离开的时候,设置高亮星星
  this.params.eleBox.addEventListener('mouseleave',function(e){
    _that.params.eleBox.style.setProperty('--value', _that.params.starValue)
  })
  1. 点击的时候,记录高亮星星的信息
  this.params.eleBox.addEventListener('click',function(e){
    _that.params.starValue = _that.starLight(e.offsetX)
    _that.params.eleInput.value = _that.params.starValue;
    _that.params.eleInput.dispatchEvent(new CustomEvent('change'));
  })
  1. 记录星星的信息,手工完成
  starLight(step) {
    step = step / 26
    var starValue = Math.trunc(step)
    
    if (step < 0) {
      starValue = 0
    } else if (step - Math.trunc(step) < 0.5) {
      // 高亮一半个星星
      starValue += 0.5
    } else {
      starValue += 1
    }
    this.params.eleBox.style.setProperty('--value', starValue)
    return starValue
  }

原生评分预览

代码封装

查看demo的时候,你会发现代码是进行了简单的封装。在new Star类的时候,只需要传入几个参数就可以满足你大部分的时候的需求

  level:你要展示几个星星,可以在style上面定义,也可以在new 的时候传入
  name:如果你使用form表单提交时候的字段
  rate:自定义样式,把你想要的样式通过一个类名传递进去(背景图的形式
  const star = new Star({el:'.star',level:7,name:'star',rate:"rate"})
  star.starRender()

高技巧实现

需求还是原来的需求,之前的实现借助了js实现,效果很完美。就是如果可以用纯 css 实现那就有意思了。

张老师在看到我代码实现的时候,提了一嘴 type="range",应该可以,我想破脑袋也想不出来。后来一个同事无意间看到了我的博客,他问我是不是想过纯 css ,我说没想过。一会之后,他给我一个demo,纯css实现了,而且用来张老师提到的 type="range",震惊,这也太厉害了吧

移动端纯css实现手指移动打分

移动端基本可以放心使用

浏览器的话要做一点点兼容处理

谷歌浏览器

<input type="range" name="star" min="0" max="5" step="0.5">
input[type="range"]{
      -webkit-appearance: none;
      width: 100px;
      margin: 0;
      outline: 0;
  }
  input[type="range" i]::-webkit-slider-runnable-track {
      background: coral;
      height: 20px;
      -webkit-mask: url("data:image/svg+xml,%3Csvg width='12' height='11' viewBox='0 0 12 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 0l1.693 3.67 4.013.476L8.74 6.89l.788 3.964L6 8.88l-3.527 1.974.788-3.964L.294 4.146l4.013-.476L6 0z' fill='%23F67600'/%3E%3C/svg%3E");
      -webkit-mask-size: 20px;
      -webkit-mask-repeat: repeat-x;
  }
  input[type="range" i]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 0;
      height: 100%;
      box-shadow: 999px 0px 0px 999px #E8EAED;
  }

火狐浏览器

  input[type=range]{
      -webkit-mask: url("data:image/svg+xml,%3Csvg width='12' height='11' viewBox='0 0 12 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 0l1.693 3.67 4.013.476L8.74 6.89l.788 3.964L6 8.88l-3.527 1.974.788-3.964L.294 4.146l4.013-.476L6 0z' fill='%23F67600'/%3E%3C/svg%3E");
      -webkit-mask-size: 20px;
      -webkit-mask-repeat: repeat-x;
      height: 20px;
  }
  input[type=range]::-moz-range-track{
      background: #E8EAED;
      height: inherit;
  }
  input[type=range]::-moz-range-progress {
      background: coral;
      height: inherit;
  }
  input[type=range]::-moz-range-thumb {
      width: 0;
      opacity: 0;
  }

总结

我的同事们脑子里装一定是的百科全书,行走的谷歌,仿佛就没有他们不知道的东西。


在技术的历史长河中,虽然我们素未谋面,却已相识已久,很微妙也很知足。互联网让世界变得更小,你我之间更近。

在逝去的青葱岁月中,虽然我们未曾相遇,却共同经历着一样的情愫。谁的青春不曾迷茫或焦虑亦是无奈,谁不曾年少过

在未来的日子里,让我们共享好的文章,共同学习进步。有不错的文章记得分享给我,我不会写好的文章,所以我只能做一个搬运工

我叫 sunseekers(张敏) ,千千万万个张敏与你同在,18年电子商务专业毕业,毕业后在前端搬砖

如果喜欢我的话,恰巧我也喜欢你的话,让我们手拉手,肩并肩共同前行,相互学习,互相鼓励

文档信息

Search

    Table of Contents