123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- <template>
- <view
- class="u-slider"
- :style="[addStyle(customStyle)]"
- >
- <template v-if="!useNative || isRange">
- <view ref="u-slider-inner" class="u-slider-inner" @click="onClick"
- @onTouchStart="onTouchStart2($event, 1)" @touchmove="onTouchMove2($event, 1)"
- @touchend="onTouchEnd2($event, 1)" @touchcancel="onTouchEnd2($event, 1)"
- :class="[disabled ? 'u-slider--disabled' : '']" :style="{
- height: (isRange && showValue) ? (getPx(blockSize) + 24) + 'px' : (getPx(blockSize)) + 'px',
- }"
- >
- <view ref="u-slider__base"
- class="u-slider__base"
- :style="[
- {
- height: height,
- backgroundColor: inactiveColor
- }
- ]"
- >
- </view>
- <view
- @click="onClick"
- class="u-slider__gap"
- :style="[
- barStyle,
- {
- height: height,
- marginTop: '-' + height,
- backgroundColor: activeColor
- }
- ]"
- >
- </view>
- <view v-if="isRange"
- class="u-slider__gap u-slider__gap-0"
- :style="[
- barStyle0,
- {
- height: height,
- marginTop: '-' + height,
- backgroundColor: inactiveColor
- }
- ]"
- >
- </view>
- <text v-if="isRange && showValue"
- class="u-slider__show-range-value" :style="{left: (getPx(barStyle0.width) + getPx(blockSize)/2) + 'px'}">
- {{ this.rangeValue[0] }}
- </text>
- <text v-if="isRange && showValue"
- class="u-slider__show-range-value" :style="{left: (getPx(barStyle.width) + getPx(blockSize)/2) + 'px'}">
- {{ this.rangeValue[1] }}
- </text>
- <template v-if="isRange">
- <view class="u-slider__button-wrap u-slider__button-wrap-0" @touchstart="onTouchStart($event, 0)"
- @touchmove="onTouchMove($event, 0)" @touchend="onTouchEnd($event, 0)"
- @touchcancel="onTouchEnd($event, 0)" :style="{left: (getPx(barStyle0.width) + getPx(blockSize)/2) + 'px'}">
- <slot v-if="$slots.default || $slots.$default"/>
- <view v-else class="u-slider__button" :style="[blockStyle, {
- height: getPx(blockSize, true),
- width: getPx(blockSize, true),
- backgroundColor: blockColor
- }]"></view>
- </view>
- </template>
- <view class="u-slider__button-wrap" @touchstart="onTouchStart"
- @touchmove="onTouchMove" @touchend="onTouchEnd"
- @touchcancel="onTouchEnd" :style="{left: (getPx(barStyle.width) + getPx(blockSize)/2) + 'px'}">
- <slot v-if="$slots.default || $slots.$default"/>
- <view v-else class="u-slider__button" :style="[blockStyle, {
- height: getPx(blockSize, true),
- width: getPx(blockSize, true),
- backgroundColor: blockColor
- }]"></view>
- </view>
- </view>
- <view class="u-slider__show-value" v-if="showValue && !isRange">{{ modelValue }}</view>
- </template>
- <slider
- class="u-slider__native"
- v-else
- :min="min"
- :max="max"
- :step="step"
- :value="modelValue"
- :activeColor="activeColor"
- :backgroundColor="inactiveColor"
- :blockSize="getPx(blockSize)"
- :blockColor="blockColor"
- :showValue="showValue"
- :disabled="disabled"
- @changing="changingHandler"
- @change="changeHandler"
- ></slider>
- </view>
- </template>
- <script>
- import { props } from './props';
- import { mpMixin } from '../../libs/mixin/mpMixin';
- import { mixin } from '../../libs/mixin/mixin';
- import { addStyle, getPx, sleep } from '../../libs/function/index.js';
-
- const dom = uni.requireNativePlugin('dom')
-
-
- export default {
- name: 'u-slider',
- mixins: [mpMixin, mixin, props],
- emits: ["start", "changing", "change", "update:modelValue"],
- data() {
- return {
- startX: 0,
- status: 'end',
- newValue: 0,
- distanceX: 0,
- startValue0: 0,
- startValue: 0,
- barStyle0: {},
- barStyle: {},
- sliderRect: {
- left: 0,
- width: 0
- }
- };
- },
- watch: {
-
- modelValue(n) {
-
- if(this.status == 'end') this.updateValue(this.modelValue, false);
- },
-
-
- value(n) {
-
- if(this.status == 'end') this.updateValue(this.value, false);
- }
-
- },
- created() {
- },
- async mounted() {
-
- if (!this.useNative) {
-
- this.$uGetRect('.u-slider__base').then(rect => {
- this.sliderRect = rect;
- this.init()
- });
-
-
- await sleep(30)
- const ref = this.$refs['u-slider__base']
- ref &&
- dom.getComponentRect(ref, (res) => {
-
- this.sliderRect = {
- left: res.size.left,
- width: res.size.width
- };
- this.init()
- })
-
- }
- },
- methods: {
- addStyle,
- getPx,
- init() {
- if (this.isRange) {
- this.updateValue(this.rangeValue[0], false, 0);
- this.updateValue(this.rangeValue[1], false, 1);
- } else {
-
- this.updateValue(this.modelValue, false);
-
-
- this.updateValue(this.value, false);
-
- }
- },
-
- changingHandler(e) {
- const {
- value
- } = e.detail
-
-
- this.$emit("update:modelValue", value);
-
-
- this.$emit("input", value);
-
-
- this.$emit('changing', value)
- },
-
- changeHandler(e) {
- const {
- value
- } = e.detail
-
-
- this.$emit("update:modelValue", value);
-
-
- this.$emit("input", value);
-
-
- this.$emit('change', value);
- },
- onTouchStart(event, index = 1) {
- if (this.disabled) return;
- this.startX = 0;
-
- let touches = event.touches[0];
-
- this.startX = touches.clientX;
-
- if (this.isRange) {
- this.startValue0 = this.format(this.rangeValue[0], 0);
- this.startValue = this.format(this.rangeValue[1], 1);
- } else {
-
- this.startValue = this.format(this.modelValue);
-
-
- this.startValue = this.format(this.value);
-
- }
-
- this.status = 'start';
- let clientX = 0;
-
- clientX = touches.clientX;
-
-
- clientX = touches.screenX;
-
- this.distanceX = clientX - this.sliderRect.left;
-
-
- this.newValue = ((this.distanceX / this.sliderRect.width) * (this.max - this.min)) + parseFloat(this.min);
- this.status = 'moving';
-
- this.$emit('changing');
- this.updateValue(this.newValue, true, index);
- },
- onTouchMove(event, index = 1) {
- if (this.disabled) return;
-
-
- if (this.status == 'start') this.$emit('start');
- let touches = event.touches[0];
- console.log('touchs', touches)
-
- let clientX = 0;
-
- clientX = touches.clientX;
-
-
- clientX = touches.screenX;
-
- this.distanceX = clientX - this.sliderRect.left;
-
-
- this.newValue = ((this.distanceX / this.sliderRect.width) * (this.max - this.min)) + parseFloat(this.min);
- this.status = 'moving';
-
- this.$emit('changing');
- this.updateValue(this.newValue, true, index);
- },
- onTouchEnd(event, index = 1) {
- if (this.disabled) return;
- if (this.status === 'moving') {
- this.updateValue(this.newValue, false, index);
- this.$emit('change');
- }
- this.status = 'end';
- },
- onTouchStart2(event, index = 1) {
- if (!this.isRange) {
-
- }
- },
- onTouchMove2(event, index = 1) {
- if (!this.isRange) {
-
- }
- },
- onTouchEnd2(event, index = 1) {
- if (!this.isRange) {
-
- }
- },
- onClick(event) {
-
- if (this.disabled) return;
-
-
-
-
- let clientX = event.detail.x - this.sliderRect.left
- this.newValue = ((clientX / this.sliderRect.width) * (this.max - this.min)) + parseFloat(this.min);
- this.updateValue(this.newValue, false, 1);
-
- },
- updateValue(value, drag, index = 1) {
-
- let valueFormat = this.format(value, index);
-
- if(valueFormat > this.max ) {
- valueFormat = this.max
- }
-
- let width = Math.min((valueFormat - this.min) / (this.max - this.min) * this.sliderRect.width, this.sliderRect.width)
- let barStyle = {
- width: width + 'px'
- };
-
- if (drag == true) {
- barStyle.transition = 'none';
- } else {
-
- delete barStyle.transition;
- }
-
- if (this.isRange) {
- this.rangeValue[index] = valueFormat;
- this.$emit("update:modelValue", this.rangeValue);
- } else {
-
- this.$emit("update:modelValue", valueFormat);
-
-
- this.$emit("input", valueFormat);
-
- }
- switch (index) {
- case 0:
- this.barStyle0 = {...barStyle};
- break;
- case 1:
- this.barStyle = {...barStyle};
- break;
- default:
- break;
- }
-
- },
- format(value, index = 1) {
-
- if (this.isRange) {
- switch (index) {
- case 0:
- return Math.round(
- Math.max(this.min, Math.min(value, this.rangeValue[1] - parseInt(this.step),this.max))
- / parseInt(this.step)
- ) * parseInt(this.step);
- break;
- case 1:
- return Math.round(
- Math.max(this.min, this.rangeValue[0] + parseInt(this.step), Math.min(value, this.max))
- / parseInt(this.step)
- ) * parseInt(this.step);
- break;
- default:
- break;
- }
- } else {
- return Math.round(
- Math.max(this.min, Math.min(value, this.max))
- / parseInt(this.step)
- ) * parseInt(this.step);
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- @import "../../libs/css/components.scss";
- .u-slider {
- position: relative;
- display: flex;
- flex-direction: row;
- align-items: center;
- &__native {
- flex: 1;
- }
- &-inner {
- flex: 1;
- display: flex;
- flex-direction: column;
- position: relative;
- border-radius: 999px;
- padding: 10px 18px;
- justify-content: center;
- }
- &__show-value {
- margin: 10px 18px 10px 0px;
- }
- &__show-range-value {
- padding-top: 2px;
- font-size: 12px;
- line-height: 12px;
- position: absolute;
- bottom: 0;
- }
- &__base {
- background-color: #ebedf0;
- }
- /* #ifndef APP-NVUE */
- &-inner:before {
- position: absolute;
- right: 0;
- left: 0;
- content: '';
- top: -8px;
- bottom: -8px;
- z-index: -1;
- }
- /* #endif */
- &__gap {
- position: relative;
- border-radius: 999px;
- transition: width 0.2s;
- background-color: #1989fa;
- }
- &__button {
- width: 24px;
- height: 24px;
- border-radius: 50%;
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
- background-color: #fff;
- transform: scale(0.9);
- /* #ifdef H5 */
- cursor: pointer;
- /* #endif */
- }
- &__button-wrap {
- position: absolute;
- // transform: translate3d(50%, -50%, 0);
- }
- &--disabled {
- opacity: 0.5;
- }
- }
- </style>
|