/**
|
* CNumberValve
|
* @author Tevin
|
*/
|
|
<template>
|
<view class="c-number-valve">
|
<view
|
class="c-number-input"
|
@tap="evt => handleOpen()"
|
>
|
<AtInput
|
ref="input"
|
:name="itemRes.name"
|
:title="itemRes.label"
|
:required="itemRes.required"
|
:disabled="itemRes.disabled"
|
:error="itemRes.error"
|
:value="itemRes.formData[itemRes.name]"
|
>
|
<view class="at-icon at-icon-chevron-right"></view>
|
</AtInput>
|
</view>
|
<AtRange
|
:min="range[0]"
|
:max="range[1]"
|
:value="[0, itemRes.formData[itemRes.name]]"
|
:onChange="evt => evt && itemRes.onChange(evt[1])"
|
/>
|
<AtFloatLayout
|
:isOpened="opened"
|
:onClose="evt => handleClose()"
|
>
|
<view class="c-number-valve-slider">
|
<view
|
class="container"
|
ref="slider"
|
>
|
<view class="min"><text class="text">{{range[0]}}</text></view>
|
<view class="max"><text class="text">{{range[1]}}</text></view>
|
<view class="rail"></view>
|
<view
|
class="track"
|
:style="{width:sliderLeft + '%'}"
|
></view>
|
<view
|
class="slider"
|
:style="{left:sliderLeft + '%'}"
|
>
|
<view
|
class="circle"
|
@touchstart="evt => handleTouchStart()"
|
@touchmove="evt => handleTouchMove(evt)"
|
></view>
|
<view class="current"><text class="text">{{current}}</text></view>
|
</view>
|
</view>
|
<view class="btn">
|
<AtButton
|
size="small"
|
:onClick="evt => handleChangeVal('left')"
|
>< 减小</AtButton>
|
<AtButton
|
size="small"
|
:onClick="evt => handleChangeVal('right')"
|
>增加 ></AtButton>
|
</view>
|
<view class="tips">请<text class="bold"> 拖动滑块 </text>或<text class="bold"> 点击按钮 </text>改变数值</view>
|
</view>
|
</AtFloatLayout>
|
</view>
|
</template>
|
|
<script>
|
import Taro from '@tarojs/taro';
|
import { $ } from '@tarojs/extend';
|
import { AtInput, AtFloatLayout, AtButton, AtRange } from 'taro-ui-vue';
|
import './cNumberValve.scss';
|
|
export default {
|
name: 'CNumberValve',
|
components: {
|
AtInput,
|
AtFloatLayout,
|
AtButton,
|
AtRange,
|
},
|
props: {
|
// 表单数据资源(表单组件内部机制专用)
|
itemRes: Object,
|
// 占位提示
|
placeholder: String,
|
// 取值范围
|
range: {
|
type: Array,
|
default: [0, 100],
|
},
|
// 步长
|
step: {
|
type: Number,
|
default: 1,
|
},
|
},
|
data() {
|
return {
|
opened: false,
|
rect: { width: 0, left: 0 },
|
current: 0,
|
sliderLeft: 0,
|
};
|
},
|
computed: {},
|
methods: {
|
handleOpen() {
|
this.opened = true;
|
setTimeout(() => {
|
this.updateRect();
|
}, 100);
|
},
|
handleClose() {
|
this.opened = false;
|
},
|
handleTouchStart() {
|
this.updateRect();
|
},
|
handleTouchMove(event) {
|
if (this.disabled) {
|
return;
|
}
|
event.stopPropagation();
|
const clientX = event.touches[0].clientX;
|
const targetValue = clientX - this.rect.left;
|
const distance = Math.min(Math.max(targetValue, 0), this.rect.width);
|
const sliderLeft = Math.floor((distance / this.rect.width) * 100);
|
const sliderValue =
|
Math.round((sliderLeft / 100) * (this.range[1] - this.range[0])) +
|
this.range[0];
|
this.sliderLeft = sliderLeft;
|
this.current = sliderValue;
|
this.itemRes.onChange(sliderValue);
|
},
|
updateRect() {
|
let $slider = null;
|
if (process.env.TARO_ENV === 'h5') {
|
$slider = $(this.$refs.slider.$el);
|
} else if (process.env.TARO_ENV === 'weapp') {
|
$slider = $(this.$refs.slider);
|
}
|
Taro.createSelectorQuery()
|
.select('#' + this.$refs.slider.uid)
|
.boundingClientRect(rect => {
|
this.rect.width = rect.width;
|
this.rect.left = rect.left;
|
})
|
.exec();
|
},
|
handleChangeVal(type, value) {
|
this.updateRect();
|
let currentNext = 0;
|
if (type === 'left') {
|
currentNext = this.current - this.step;
|
} else if (type === 'right') {
|
currentNext = this.current + this.step;
|
} else if (type === 'change') {
|
currentNext = value;
|
}
|
const sliderLeft = Math.round(
|
((currentNext - this.range[0]) / (this.range[1] - this.range[0])) * 100
|
);
|
this.sliderLeft = sliderLeft;
|
this.current = currentNext;
|
this.itemRes.onChange(currentNext);
|
},
|
},
|
mounted() {
|
const itemName = this.itemRes.name;
|
this.$watch('itemRes.formData.' + itemName, value => {
|
if (value !== this.current) {
|
this.handleChangeVal('change', value);
|
}
|
});
|
},
|
};
|
</script>
|