¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="u-rate" |
| | | :id="elId" |
| | | ref="u-rate" |
| | | :style="[$u.addStyle(customStyle)]" |
| | | > |
| | | <view |
| | | class="u-rate__content" |
| | | @touchmove.stop="touchMove" |
| | | @touchend.stop="touchEnd" |
| | | > |
| | | <view |
| | | class="u-rate__content__item" |
| | | v-for="(item, index) in Number(count)" |
| | | :key="index" |
| | | :class="[elClass]" |
| | | > |
| | | <view |
| | | class="u-rate__content__item__icon-wrap" |
| | | ref="u-rate__content__item__icon-wrap" |
| | | @tap.stop="clickHandler($event, index + 1)" |
| | | > |
| | | <u-icon |
| | | :name=" |
| | | Math.floor(activeIndex) > index |
| | | ? activeIcon |
| | | : inactiveIcon |
| | | " |
| | | :color=" |
| | | disabled |
| | | ? '#c8c9cc' |
| | | : Math.floor(activeIndex) > index |
| | | ? activeColor |
| | | : inactiveColor |
| | | " |
| | | :custom-style="{ |
| | | 'padding-left': $u.addUnit(gutter / 2), |
| | | 'padding-right': $u.addUnit(gutter / 2) |
| | | }" |
| | | :size="size" |
| | | ></u-icon> |
| | | </view> |
| | | <view |
| | | v-if="allowHalf" |
| | | @tap.stop="clickHandler($event, index + 1)" |
| | | class="u-rate__content__item__icon-wrap u-rate__content__item__icon-wrap--half" |
| | | :style="[{ |
| | | width: $u.addUnit(rateWidth / 2), |
| | | }]" |
| | | ref="u-rate__content__item__icon-wrap" |
| | | > |
| | | <u-icon |
| | | :name=" |
| | | Math.ceil(activeIndex) > index |
| | | ? activeIcon |
| | | : inactiveIcon |
| | | " |
| | | :color=" |
| | | disabled |
| | | ? '#c8c9cc' |
| | | : Math.ceil(activeIndex) > index |
| | | ? activeColor |
| | | : inactiveColor |
| | | " |
| | | :custom-style="{ |
| | | 'padding-left': $u.addUnit(gutter / 2), |
| | | 'padding-right': $u.addUnit(gutter / 2) |
| | | }" |
| | | :size="size" |
| | | ></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import props from './props.js'; |
| | | |
| | | // #ifdef APP-NVUE |
| | | const dom = weex.requireModule("dom"); |
| | | // #endif |
| | | /** |
| | | * rate è¯å |
| | | * @description 该ç»ä»¶ä¸è¬ç¨äºæ»¡æåº¦è°æ¥ï¼æåè¯åçåºæ¯ |
| | | * @tutorial https://www.uviewui.com/components/rate.html |
| | | * @property {String | Number} value ç¨äºv-modelååç»å®éä¸çæææ°é (é»è®¤ 1 ) |
| | | * @property {String | Number} count æå¤å¯éçæææ°é ï¼é»è®¤ 5 ï¼ |
| | | * @property {Boolean} disabled æ¯å¦ç¦æ¢ç¨æ·æä½ ï¼é»è®¤ false ï¼ |
| | | * @property {Boolean} readonly æ¯å¦åªè¯» ï¼é»è®¤ false ï¼ |
| | | * @property {String | Number} size ææç大å°ï¼åä½px ï¼é»è®¤ 18 ï¼ |
| | | * @property {String} inactiveColor æªé䏿æçé¢è² ï¼é»è®¤ '#b2b2b2' ï¼ |
| | | * @property {String} activeColor éä¸çææé¢è² ï¼é»è®¤ '#FA3534' ï¼ |
| | | * @property {String | Number} gutter ææä¹é´çè·ç¦» ï¼é»è®¤ 4 ï¼ |
| | | * @property {String | Number} minCount æå°é䏿æçä¸ªæ° ï¼é»è®¤ 1 ï¼ |
| | | * @property {Boolean} allowHalf æ¯å¦å
许åæéæ© ï¼é»è®¤ false ï¼ |
| | | * @property {String} activeIcon é䏿¶ç徿 åï¼åªè½ä¸ºuViewçå
ç½®å¾æ ï¼é»è®¤ 'star-fill' ï¼ |
| | | * @property {String} inactiveIcon æªé䏿¶ç徿 åï¼åªè½ä¸ºuViewçå
ç½®å¾æ ï¼é»è®¤ 'star' ï¼ |
| | | * @property {Boolean} touchable æ¯å¦å¯ä»¥éè¿æ»å¨æå¿éæ©è¯å ï¼é»è®¤ 'true' ï¼ |
| | | * @property {Object} customStyle ç»ä»¶çæ ·å¼ï¼å¯¹è±¡å½¢å¼ |
| | | * @event {Function} change éä¸çææåçååæ¶è§¦å |
| | | * @example <u-rate :count="count" :value="2"></u-rate> |
| | | */ |
| | | export default { |
| | | name: "u-rate", |
| | | mixins: [uni.$u.mpMixin, uni.$u.mixin,props], |
| | | data() { |
| | | return { |
| | | // çæä¸ä¸ªå¯ä¸idï¼å¦åä¸ä¸ªé¡µé¢å¤ä¸ªè¯åç»ä»¶ï¼ä¼é æå²çª |
| | | elId: uni.$u.guid(), |
| | | elClass: uni.$u.guid(), |
| | | rateBoxLeft: 0, // è¯åçå左边å°å±å¹å·¦è¾¹çè·ç¦»ï¼ç¨äºæ»å¨éæ©æ¶è®¡ç®è·ç¦» |
| | | activeIndex: this.value, |
| | | rateWidth: 0, // æ¯ä¸ªææç宽度 |
| | | // æ è¯æ¯å¦æ£å¨æ»å¨ï¼ç±äºiOSäºä»¶ä¸touchæ¯clickå
触åï¼å¯¼è´å¿«éæ»å¨ç»æåï¼æ¥ç触åclickï¼å¯¼è´äºä»¶æ··ä¹±èåºé |
| | | moving: false, |
| | | }; |
| | | }, |
| | | watch: { |
| | | value(val) { |
| | | this.activeIndex = val; |
| | | }, |
| | | activeIndex: 'emitEvent' |
| | | }, |
| | | methods: { |
| | | init() { |
| | | uni.$u.sleep().then(() => { |
| | | this.getRateItemRect(); |
| | | this.getRateIconWrapRect(); |
| | | }) |
| | | }, |
| | | // è·åè¯åç»ä»¶çåçå¸å±ä¿¡æ¯ |
| | | async getRateItemRect() { |
| | | await uni.$u.sleep(); |
| | | // uViewå°è£
çè·åèç¹çæ¹æ³ï¼è¯¦è§ææ¡£ |
| | | // #ifndef APP-NVUE |
| | | this.$uGetRect("#" + this.elId).then((res) => { |
| | | this.rateBoxLeft = res.left; |
| | | }); |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | dom.getComponentRect(this.$refs["u-rate"], (res) => { |
| | | this.rateBoxLeft = res.size.left; |
| | | }); |
| | | // #endif |
| | | }, |
| | | // è·åå个ææç尺寸 |
| | | getRateIconWrapRect() { |
| | | // uViewå°è£
çè·åèç¹çæ¹æ³ï¼è¯¦è§ææ¡£ |
| | | // #ifndef APP-NVUE |
| | | this.$uGetRect("." + this.elClass).then((res) => { |
| | | this.rateWidth = res.width; |
| | | }); |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | dom.getComponentRect( |
| | | this.$refs["u-rate__content__item__icon-wrap"][0], |
| | | (res) => { |
| | | this.rateWidth = res.size.width; |
| | | } |
| | | ); |
| | | // #endif |
| | | }, |
| | | // æææ»å¨ |
| | | touchMove(e) { |
| | | // å¦æç¦æ¢éè¿æå¨æ»å¨éæ©ï¼è¿å |
| | | if (!this.touchable) { |
| | | return; |
| | | } |
| | | this.preventEvent(e); |
| | | const x = e.changedTouches[0].pageX; |
| | | this.getActiveIndex(x); |
| | | }, |
| | | // 忢æ»å¨ |
| | | touchEnd(e) { |
| | | // å¦æç¦æ¢éè¿æå¨æ»å¨éæ©ï¼è¿å |
| | | if (!this.touchable) { |
| | | return; |
| | | } |
| | | this.preventEvent(e); |
| | | const x = e.changedTouches[0].pageX; |
| | | this.getActiveIndex(x); |
| | | }, |
| | | // éè¿ç¹å»ï¼ç´æ¥éä¸ |
| | | clickHandler(e, index) { |
| | | // iosä¸ï¼movingç¶æåæ¶äºä»¶è§¦å |
| | | if (uni.$u.os() === "ios" && this.moving) { |
| | | return; |
| | | } |
| | | this.preventEvent(e); |
| | | let x = 0; |
| | | // ç¹å»æ¶ï¼å¨nvueä¸ï¼æ æ³è·å¾ç¹å»çåæ ï¼æä»¥æ æ³å®ç°ç¹å»åæéæ© |
| | | // #ifndef APP-NVUE |
| | | x = e.changedTouches[0].pageX; |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | // nvueä¸ï¼æ æ³éè¿ç¹å»è·å¾åæ ä¿¡æ¯ï¼è¿ééè¿å
ç´ çä½ç½®å°ºå¯¸å¼æ¨¡æåæ |
| | | x = index * this.rateWidth + this.rateBoxLeft; |
| | | // #endif |
| | | this.getActiveIndex(x,true); |
| | | }, |
| | | // ååºäºä»¶ |
| | | emitEvent() { |
| | | // ååºchangeäºä»¶ |
| | | this.$emit("change", this.activeIndex); |
| | | // åæ¶ä¿®æ¹ååç»å®çvalueçå¼ |
| | | this.$emit("input", this.activeIndex); |
| | | }, |
| | | // è·åå½åæ¿æ´»çè¯å徿 |
| | | getActiveIndex(x,isClick = false) { |
| | | if (this.disabled || this.readonly) { |
| | | return; |
| | | } |
| | | // 夿å½åæä½çç¹çxåæ å¼ï¼æ¯å¦å¨å
许çè¾¹çèå´å
|
| | | const allRateWidth = this.rateWidth * this.count + this.rateBoxLeft; |
| | | // 妿å°äºç¬¬ä¸ä¸ªå¾æ ç左边çï¼è®¾ç½®ä¸ºæå°å¼ï¼å¦æå¤§äºææå¾æ ç宽度ï¼å设置为æå¤§å¼ |
| | | x = uni.$u.range(this.rateBoxLeft, allRateWidth, x) - this.rateBoxLeft |
| | | // æ»å¨ç¹ç¸å¯¹äºè¯åçå左边çè·ç¦» |
| | | const distance = x; |
| | | // æ»å¨çè·ç¦»ï¼ç¸å½äºå¤å°é¢ææ |
| | | let index; |
| | | // 夿æ¯å¦å
è®¸åæ |
| | | if (this.allowHalf) { |
| | | index = Math.floor(distance / this.rateWidth); |
| | | // åä½ï¼å¤æå°æ°çåºé´èå´ |
| | | const decimal = distance % this.rateWidth; |
| | | if (decimal <= this.rateWidth / 2 && decimal > 0) { |
| | | index += 0.5; |
| | | } else if (decimal > this.rateWidth / 2) { |
| | | index++; |
| | | } |
| | | } else { |
| | | index = Math.floor(distance / this.rateWidth); |
| | | // åä½ï¼å¤æå°æ°çåºé´èå´ |
| | | const decimal = distance % this.rateWidth; |
| | | // éåææ¶ï¼åªæè¶
è¿äºå¾æ çä¸åè·ç¦»ï¼æè®¤ä¸ºæ¯éæ©äºè¿é¢æ |
| | | if (isClick){ |
| | | if (decimal > 0) index++; |
| | | } else { |
| | | if (decimal > this.rateWidth / 2) index++; |
| | | } |
| | | |
| | | } |
| | | this.activeIndex = Math.min(index, this.count); |
| | | // 对æå°é¢ææçéå¶ |
| | | if (this.activeIndex < this.minCount) { |
| | | this.activeIndex = this.minCount; |
| | | } |
| | | |
| | | // 设置延æ¶ä¸ºäºè®©clickäºä»¶å¨touchmoveä¹å触å |
| | | setTimeout(() => { |
| | | this.moving = true; |
| | | }, 10); |
| | | // ä¸å®æ¶é´åï¼åæ¶æ è¯ä¸ºç§»å¨ä¸ç¶æï¼æ¯ä¸ºäºè®©clickäºä»¶æ æ |
| | | setTimeout(() => { |
| | | this.moving = false; |
| | | }, 10); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.init(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "../../libs/css/components.scss"; |
| | | $u-rate-margin: 0 !default; |
| | | $u-rate-padding: 0 !default; |
| | | $u-rate-item-icon-wrap-half-top: 0 !default; |
| | | $u-rate-item-icon-wrap-half-left: 0 !default; |
| | | |
| | | .u-rate { |
| | | @include flex; |
| | | align-items: center; |
| | | margin: $u-rate-margin; |
| | | padding: $u-rate-padding; |
| | | /* #ifndef APP-NVUE */ |
| | | touch-action: none; |
| | | /* #endif */ |
| | | |
| | | &__content { |
| | | @include flex; |
| | | |
| | | &__item { |
| | | position: relative; |
| | | |
| | | &__icon-wrap { |
| | | &--half { |
| | | position: absolute; |
| | | overflow: hidden; |
| | | top: $u-rate-item-icon-wrap-half-top; |
| | | left: $u-rate-item-icon-wrap-half-left; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .u-icon { |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | } |
| | | </style> |