微信小程序-星星评分组件支持半星/自定义尺寸

由于从网上直接copy的评分组件虽然能用,但是我找到的组件渲染做得稍差,于是准备自己改进一下。

先放一个效果图:

 

一.准备

准备类似的四张图片,图片一定要根据像素点精准对半切开,否则在小程序中会出现重叠现象。

推荐在iconfont图标库中选择自己想要的图标,下载到本地后使用【画图3D】将图片进行对半裁剪。

示例图片如下:

        


二. 组件部分

        代码的wxss部分借鉴了借鉴文章,但改进了其JS渲染部分。

        【说明】:本组件默认评分为1分,最低分为0.5分,不支持打0分。大家可自行更改JS文件stars数组中的flag1和flag2以及star_num来自定义起评分。

        在微信开发者工具中新建一个component,此次示例取名为star

        1.star.js

           【bgImgL】对应未选中左半星图片路径

           【bgfImgL】对应已选中左半星图片路径

           【bgImgR】对应未选中右半星图片路径

           【bgfImgR】对应已选中右半星图片路径

             以上四个图片路径请自行替换为本地图片路径

// components/star.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    //接收自定义的高度
    setSize:Number,
  },

  data: {
    stars: [
      {
        flag1: 2,
        flag2: 2,
        bgImgL: "/src/icons/Lstar.png",
        bgfImgL: "/src/icons/Lstar.active.png",
        bgImgR: "/src/icons/Rstar.png",
        bgfImgR: "/src/icons/Rstar.active.png",
      },
      {
        flag1: 1,
        flag2: 1,
        bgImgL: "/src/icons/Lstar.png",
        bgfImgL: "/src/icons/Lstar.active.png",
        bgImgR: "/src/icons/Rstar.png",
        bgfImgR: "/src/icons/Rstar.active.png",
      },
      {
        flag1: 1,
        flag2: 1,
        bgImgL: "/src/icons/Lstar.png",
        bgfImgL: "/src/icons/Lstar.active.png",
        bgImgR: "/src/icons/Rstar.png",
        bgfImgR: "/src/icons/Rstar.active.png",
      },
      {
        flag1: 1,
        flag2: 1,
        bgImgL: "/src/icons/Lstar.png",
        bgfImgL: "/src/icons/Lstar.active.png",
        bgImgR: "/src/icons/Rstar.png",
        bgfImgR: "/src/icons/Rstar.active.png",
      },
      {
        flag1:1,
        flag2:1,
        bgImgL: "/src/icons/Lstar.png",
        bgfImgL: "/src/icons/Lstar.active.png",
        bgImgR: "/src/icons/Rstar.png",
        bgfImgR: "/src/icons/Rstar.active.png",
      },
      
    ],
    star_num: 1,  // 默认1分  最低0.5分
    Lindex:0,  //左下标
    Rindex:0,   //右下标 
    oldScore:'', //旧分数
    newScore:''//新分数
  },

  /**
   * 组件的方法列表
   */
  methods: {
      //点击左边
    scoreL: function (e) {
      var _this = this;
      this.setData({
        oldScore:this.data.star_num
      })
      // console.log("旧分数",this.data.oldScore)
      var index = e.currentTarget.dataset.index;
      //改变分数
      _this.setData({
        star_num: index + 0.5 // 评分
      })
      this.setData({
        newScore:this.data.star_num
      })
      // console.log("新分数",this.data.newScore)
      this.judgeNum() //重新渲染星星
    },
    //点击右边
    scoreR: function (e) {
      this.setData({
        oldScore:this.data.star_num
      })
      var _this = this;
      var index = e.currentTarget.dataset.index;
      // 评分
      _this.setData({
        star_num: index + 1 // 评分
      })
      this.setData({
        newScore:this.data.star_num
      })
      this.judgeNum()
    },
    changeL(param){     //左移  1代表减 2代表加
      var that = this;
      // console.log("LL左下标",that.data.Lindex)
      // console.log("LL右下标",that.data.Rindex)
      var item ='stars['+that.data.Lindex+'].flag1'
      if(param===1){ //左移动
        // console.log("锚点1")
        const middle = that.data.Lindex 
        var item ='stars['+middle+'].flag1'
        that.setData({
          [item]:1,
          Lindex:that.data.Lindex-1
        })
      }
      if(param===2){
        // console.log("锚点2")
        const middle = that.data.Lindex + 1
        var item ='stars['+middle+'].flag1'
        that.setData({
          [item]:2,
          Lindex:that.data.Lindex+1
        })
      }
    },
    changeR(param){    //右移  1代表减 2代表加
      const that = this
      var item ='stars['+that.data.Lindex+'].flag2'
      if(param===1){ //左移动
        // console.log("锚点3")
        that.setData({
          [item]:1,
          Rindex:this.data.Rindex-1
        })
      }
      if(param===2){
        // console.log("锚点4")
        const middle = that.data.Rindex + 1
        var item ='stars['+middle+'].flag2'
        that.setData({
          [item]:2,
          Rindex:this.data.Rindex+1
        })
      }
    },
    judgeNum:function(){
      const isPoint = (this.data.oldScore) % 1 ==0? false:true
      const flag = this.data.newScore - this.data.oldScore //分差
      if(flag<0)  {//分差小于0 扣分
        if(isPoint) {  //是小数(左)
          const LorR={
            toL:true,
            toR:false,
          }
          const count = Math.abs(flag)*2  //变化的次数 LRLR
          for (var i=0;i<count;i++)
          {
            if(LorR.toL){
              this.changeL(1)
            }
            if(LorR.toR){
              this.changeR(1)
            }
            LorR.toL=!LorR.toL
            LorR.toR=!LorR.toR
          }
        }//是整数(右)
        else{
          const LorR={
            toL:false,
            toR:true,
          }
          const count = Math.abs(flag)*2  //变化的次数 LRLR
          for (var i=0;i<count;i++)
          {
            if(LorR.toL){
              this.changeL(1)
            }
            if(LorR.toR){
              this.changeR(1)
            }
            LorR.toL=!LorR.toL
            LorR.toR=!LorR.toR
          }
        }
      }  //分差大于0 加分
      else{
        if(isPoint) {//是小数
        const LorR={
          toL:false,
          toR:true,
        }
        const count = Math.abs(flag)*2  //变化的次数 LRLR
        for (var i=0;i<count;i++)
        {
          if(LorR.toL){
            this.changeL(2)
          }
          if(LorR.toR){
            this.changeR(2)
          }
          LorR.toL=!LorR.toL
          LorR.toR=!LorR.toR
        }
        }
        else{ //是整数
          const LorR={
            toL:true,
            toR:false,
          }
          const count = Math.abs(flag)*2  //变化的次数 LRLR
          for (var i=0;i<count;i++)
          {
            if(LorR.toL){
              this.changeL(2)
            }
            if(LorR.toR){
              this.changeR(2)
            }
            LorR.toL=!LorR.toL
            LorR.toR=!LorR.toR
          }
        }
     }
    },
    setNum(){  //向父组件传值
      //传入的参数名称 starNum    
      this.triggerEvent('myevent',{starNum:this.data.star_num})
    }
  }
})

        2.star.wxml

<view class="stars" bindtap="setNum">
  <view wx:for="{{stars}}" wx:key="index" class="starItem" style="--width--:{{setSize}}rpx;--height--:{{setSize}}rpx">
    <image src="{{item.flag1 == 1 ? item.bgImgL : item.bgfImgL}}" data-index="{{index}}" bindtap='scoreL'>
    </image>
    <image src="{{item.flag2 == 1 ? item.bgImgR : item.bgfImgR}}" data-index="{{index}}" bindtap='scoreR'></image>
  </view>
</view>

        3.star.wxss

.stars {
  display: flex;
  width: var(--width--);
  height: var(--height--);
  /* width: 100%;
  height: 100px; */
}

.stars view {
  position: relative;
  width: var(--width--);
  height: var(--height--);
  margin-right: 20rpx;
}

.stars view image:nth-of-type(1) {
  width: 50%;
  height: 100%;
  margin-right: -2rpx;
}
.stars view image:nth-of-type(2) {
  width: 50%;
  height: 100%;
  margin-left: -1rpx;
}

三.在页面中引用

该组件支持自定义高度,所以在其他页面中引用该组件时,需要传入一个参数来设置其宽高,尺寸为rpx,传入的参数名称为【setSize】,并且该组件支持将每次点击的评分回传到引入该组件的页面。

        1.引入页面的json文件

        组件的位置请自行替换为自己组件的位置,该处只为示例代码

{
  "usingComponents": {
    "star":"../../../components/star/star"
  }
}

        2.引入页面的wxml文件

//setSize=100 表示将组件的高度设置为100rpx  
//bind:myevent =“setStarNum”用于接收子组件回传的评分数值
//需在JS文件中写一个【setStarNum】函数
<star setSize='100' bind:myevent="setStarNum"></star>

        3.引入页面的js文件

 
 setStarNum(e){
    console.log("获得的评分为",e.detail.starNum)
  },

  //评分已经拿到了,如何处理及操作可自行编写

  四.效果演示

        经过优化后的渲染过程不会出现原来copy的代码中星星频闪的问题,实际变化过程中要流畅很多,放两种图片自行对比

        1.已优化

         2.未优化

                在切换时可看到明显的频闪现象。有兴趣的具体有可以去看借鉴的原文章,频闪是因为其每次都将原来星星的状态清零且重新渲染时未按顺序填色导致的。

                                     

 

编写不易,若使用过程中出现bug欢迎交流指正。

        

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340