uni-rate.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <template>
  2. <view class="uni-rate">
  3. <view v-for="(star, index) in stars" :key="index" :style="{ marginLeft: margin + 'px' }" class="uni-rate-icon" @click="_onClick(index)">
  4. <uni-icon :size="size" :color="color" :type="isFill ? 'star-filled' : 'star'" />
  5. <view :style="{ width: star.activeWitch }" class="uni-rate-icon-on">
  6. <uni-icon :size="size" :color="activeColor" type="star-filled" />
  7. </view>
  8. </view>
  9. </view>
  10. </template>
  11. <script>
  12. import uniIcon from '../uni-icon/uni-icon.vue'
  13. export default {
  14. name: 'UniRate',
  15. components: {
  16. uniIcon
  17. },
  18. props: {
  19. isFill: {
  20. // 星星的类型,是否镂空
  21. type: Boolean,
  22. default: true
  23. },
  24. color: {
  25. // 星星的颜色
  26. type: String,
  27. default: '#ececec'
  28. },
  29. activeColor: {
  30. // 星星选中状态颜色
  31. type: String,
  32. default: '#ffca3e'
  33. },
  34. size: {
  35. // 星星的大小
  36. type: [Number, String],
  37. default: 24
  38. },
  39. value: {
  40. // 当前评分
  41. type: [Number, String],
  42. default: 0
  43. },
  44. max: {
  45. // 最大评分
  46. type: [Number, String],
  47. default: 5
  48. },
  49. margin: {
  50. // 星星的间距
  51. type: [Number, String],
  52. default: 0
  53. },
  54. disabled: {
  55. // 是否可点击
  56. type: Boolean,
  57. default: false
  58. }
  59. },
  60. data() {
  61. return {
  62. valueSync: ''
  63. }
  64. },
  65. computed: {
  66. stars() {
  67. const value = Number(this.valueSync) ? Number(this.valueSync) : 0
  68. const starList = []
  69. const floorValue = Math.floor(value)
  70. const ceilValue = Math.ceil(value)
  71. for (let i = 0; i < this.max; i++) {
  72. if (floorValue > i) {
  73. starList.push({
  74. activeWitch: '100%'
  75. })
  76. } else if (ceilValue - 1 === i) {
  77. starList.push({
  78. activeWitch: (value - floorValue) * 100 + '%'
  79. })
  80. } else {
  81. starList.push({
  82. activeWitch: '0'
  83. })
  84. }
  85. }
  86. return starList
  87. }
  88. },
  89. created() {
  90. this.valueSync = this.value
  91. },
  92. methods: {
  93. _onClick(index) {
  94. if (this.disabled) {
  95. return
  96. }
  97. this.valueSync = index + 1
  98. this.$emit('change', {
  99. value: this.valueSync
  100. })
  101. }
  102. }
  103. }
  104. </script>
  105. <style>
  106. @charset "UTF-8";
  107. .uni-rate {
  108. line-height: 0;
  109. font-size: 0;
  110. display: flex;
  111. flex-direction: row
  112. }
  113. .uni-rate-icon {
  114. position: relative;
  115. line-height: 0;
  116. font-size: 0;
  117. display: inline-block
  118. }
  119. .uni-rate-icon-on {
  120. line-height: 1;
  121. position: absolute;
  122. top: 0;
  123. left: 0;
  124. overflow: hidden
  125. }
  126. </style>