123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- <template>
- <div class="input range">
- <div class="range-content" :class="{ animation: mode === modeEmun.default }" :style="{ '--percentage': percenStyle }" @click="rangeClickHandler" ref="rangeRef">
- <div class="range-locus" ref="locusRef">
- <span class="range-slide" @click.stop @mousedown="slideDownHandler">
- <span v-if="rangeTips" class="tips">{{ modelValue }}%</span>
- </span>
- </div>
- </div>
- <div v-if="rangeInput">
- <UItext v-if="inch" :modelValue="inch" class="range-text" style="pointer-events: none" />
- <UInumber v-else :modelValue="modelValue" @update:modelValue="inputUpdateHandler" :min="min" :max="max" :step="step" :ctrl="false" right class="range-text" />
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, computed, onMounted, defineProps, nextTick } from 'vue'
- import { rangePropsDesc } from './state'
- import UInumber from './number.vue'
- import UItext from './text.vue'
- const props = defineProps(rangePropsDesc)
- const emit = defineEmits(['update:modelValue'])
- const getValue = value => {
- const calcStep = Math.ceil(1 / props.step)
- const calcValue = Math.round(value * calcStep)
- const calcMin = props.min * calcStep
- const calcMax = props.max * calcStep
- const newVal = calcValue >= calcMax ? calcMax : calcValue <= calcMin ? calcMin : calcValue - (calcValue % (calcStep * props.step))
- return newVal / calcStep
- }
- const percen = computed({
- get() {
- return (Number(props.modelValue) - props.min) / (props.max - props.min)
- },
- set(val) {
- const len = props.max - props.min
- let num
- if (props.limit > 0 && props.min + len * val > props.limit) {
- num = getValue(props.limit)
- } else {
- num = getValue(props.min + len * val)
- }
- emit('update:modelValue', num)
- },
- })
- const percenStyle = computed(() => `${percen.value * 100}%`)
- const inputUpdateHandler = val => {
- let num
- if (props.limit > 0 && val > props.limit) {
- num = getValue(props.limit)
- } else {
- num = getValue(val)
- }
- emit('update:modelValue', num)
- }
- const modeEmun = {
- slide: 0,
- default: 1,
- }
- const mode = ref(modeEmun.default)
- const locusWidth = ref(0)
- const locusRef = ref(null)
- const rangeWidth = ref(0)
- const rangeRef = ref(null)
- onMounted(() => {
- nextTick(() => {
- locusWidth.value = locusRef.value.offsetWidth
- rangeWidth.value = rangeRef.value.offsetWidth
- })
- })
- const rangeClickHandler = ev => {
- percen.value = ev.offsetX / rangeWidth.value
- console.log(ev.offsetX, rangeWidth.value)
- //首次点击,获取limit的值
- let t = setTimeout(() => {
- const len = props.max - props.min
- if (props.limit > 0 && props.min + len * percen.value > props.limit) {
- percen.value = (props.limit - props.min) / len
- } else {
- // percen.value = ev.offsetX / rangeWidth.value
- }
- clearTimeout(t)
- }, 0)
- }
- const parent = document.documentElement
- const player = document.querySelector('.player[name="main"]')
- const slideDownHandler = ev => {
- ev.preventDefault()
- const moveStartX = ev.clientX
- const startPercen = percen.value
- mode.value = modeEmun.slide
- const moveHandler = ev => {
- ev.preventDefault()
- const moveX = ev.clientX - moveStartX
- const readyPercen = startPercen + moveX / locusWidth.value
- percen.value = readyPercen < 0 ? 0 : readyPercen > 1 ? 1 : readyPercen
- }
- const upHandler = _ => {
- mode.value = modeEmun.default
- parent.removeEventListener('mousemove', moveHandler, false)
- parent.removeEventListener('mouseup', upHandler, false)
- player.removeEventListener('mouseup', upHandler, false)
- }
- parent.addEventListener('mousemove', moveHandler, false)
- parent.addEventListener('mouseup', upHandler, false)
- player.addEventListener('mouseup', upHandler, false)
- }
- </script>
|