123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- <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: `0 ${$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: `0 ${$u.addUnit(gutter / 2)}`
- }"
- :size="size"
- ></u-icon>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import props from './props.js';
-
- const dom = weex.requireModule("dom");
-
-
- export default {
- name: "u-rate",
- mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
- data() {
- return {
-
- elId: uni.$u.guid(),
- elClass: uni.$u.guid(),
- rateBoxLeft: 0,
- activeIndex: this.value,
- rateWidth: 0,
-
- 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();
-
-
- this.$uGetRect("#" + this.elId).then((res) => {
- this.rateBoxLeft = res.left;
- });
-
-
- dom.getComponentRect(this.$refs["u-rate"], (res) => {
- this.rateBoxLeft = res.size.left;
- });
-
- },
-
- getRateIconWrapRect() {
-
-
- this.$uGetRect("." + this.elClass).then((res) => {
- this.rateWidth = res.width;
- });
-
-
- dom.getComponentRect(
- this.$refs["u-rate__content__item__icon-wrap"][0],
- (res) => {
- this.rateWidth = res.size.width;
- }
- );
-
- },
-
- 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) {
-
- if (uni.$u.os() === "ios" && this.moving) {
- return;
- }
- this.preventEvent(e);
- let x = 0;
-
-
- x = e.changedTouches[0].pageX;
-
-
-
- x = index * this.rateWidth + this.rateBoxLeft;
-
- this.getActiveIndex(x,true);
- },
-
- emitEvent() {
-
- this.$emit("change", this.activeIndex);
-
- this.$emit("input", this.activeIndex);
- },
-
- getActiveIndex(x,isClick = false) {
- if (this.disabled || this.readonly) {
- return;
- }
-
- 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;
- }
-
- setTimeout(() => {
- this.moving = true;
- }, 10);
-
- 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>
|