range.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <div class="input range">
  3. <div class="range-content" :class="{ animation: mode === modeEmun.default }" :style="{ '--percentage': percenStyle }" @click="rangeClickHandler" ref="rangeRef">
  4. <div class="range-locus" ref="locusRef">
  5. <span class="range-slide" @click.stop @mousedown="slideDownHandler">
  6. <span v-if="rangeTips" class="tips">{{ modelValue }}%</span>
  7. </span>
  8. </div>
  9. </div>
  10. <div v-if="rangeInput">
  11. <UItext v-if="inch" :modelValue="inch" class="range-text" style="pointer-events: none" />
  12. <UInumber v-else :modelValue="modelValue" @update:modelValue="inputUpdateHandler" :min="min" :max="max" :step="step" :ctrl="false" right class="range-text" />
  13. </div>
  14. </div>
  15. </template>
  16. <script setup lang="ts">
  17. import { ref, computed, onMounted, defineProps, nextTick } from 'vue'
  18. import { rangePropsDesc } from './state'
  19. import UInumber from './number.vue'
  20. import UItext from './text.vue'
  21. const props = defineProps(rangePropsDesc)
  22. const emit = defineEmits(['update:modelValue'])
  23. const getValue = value => {
  24. const calcStep = Math.ceil(1 / props.step)
  25. const calcValue = Math.round(value * calcStep)
  26. const calcMin = props.min * calcStep
  27. const calcMax = props.max * calcStep
  28. const newVal = calcValue >= calcMax ? calcMax : calcValue <= calcMin ? calcMin : calcValue - (calcValue % (calcStep * props.step))
  29. return newVal / calcStep
  30. }
  31. const percen = computed({
  32. get() {
  33. return (Number(props.modelValue) - props.min) / (props.max - props.min)
  34. },
  35. set(val) {
  36. const len = props.max - props.min
  37. let num
  38. if (props.limit > 0 && props.min + len * val > props.limit) {
  39. num = getValue(props.limit)
  40. } else {
  41. num = getValue(props.min + len * val)
  42. }
  43. emit('update:modelValue', num)
  44. },
  45. })
  46. const percenStyle = computed(() => `${percen.value * 100}%`)
  47. const inputUpdateHandler = val => {
  48. let num
  49. if (props.limit > 0 && val > props.limit) {
  50. num = getValue(props.limit)
  51. } else {
  52. num = getValue(val)
  53. }
  54. emit('update:modelValue', num)
  55. }
  56. const modeEmun = {
  57. slide: 0,
  58. default: 1,
  59. }
  60. const mode = ref(modeEmun.default)
  61. const locusWidth = ref(0)
  62. const locusRef = ref(null)
  63. const rangeWidth = ref(0)
  64. const rangeRef = ref(null)
  65. onMounted(() => {
  66. nextTick(() => {
  67. locusWidth.value = locusRef.value.offsetWidth
  68. rangeWidth.value = rangeRef.value.offsetWidth
  69. })
  70. })
  71. const rangeClickHandler = ev => {
  72. percen.value = ev.offsetX / rangeWidth.value
  73. console.log(ev.offsetX, rangeWidth.value)
  74. //首次点击,获取limit的值
  75. let t = setTimeout(() => {
  76. const len = props.max - props.min
  77. if (props.limit > 0 && props.min + len * percen.value > props.limit) {
  78. percen.value = (props.limit - props.min) / len
  79. } else {
  80. // percen.value = ev.offsetX / rangeWidth.value
  81. }
  82. clearTimeout(t)
  83. }, 0)
  84. }
  85. const parent = document.documentElement
  86. const player = document.querySelector('.player[name="main"]')
  87. const slideDownHandler = ev => {
  88. ev.preventDefault()
  89. const moveStartX = ev.clientX
  90. const startPercen = percen.value
  91. mode.value = modeEmun.slide
  92. const moveHandler = ev => {
  93. ev.preventDefault()
  94. const moveX = ev.clientX - moveStartX
  95. const readyPercen = startPercen + moveX / locusWidth.value
  96. percen.value = readyPercen < 0 ? 0 : readyPercen > 1 ? 1 : readyPercen
  97. }
  98. const upHandler = _ => {
  99. mode.value = modeEmun.default
  100. parent.removeEventListener('mousemove', moveHandler, false)
  101. parent.removeEventListener('mouseup', upHandler, false)
  102. player.removeEventListener('mouseup', upHandler, false)
  103. }
  104. parent.addEventListener('mousemove', moveHandler, false)
  105. parent.addEventListener('mouseup', upHandler, false)
  106. player.addEventListener('mouseup', upHandler, false)
  107. }
  108. </script>