From 4aa1de9fdfcbfb63b7f93e1c10d4c464eb4483ea Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Thu, 5 Dec 2024 03:18:57 +0800 Subject: [PATCH] fix: smooth issue --- .../stage/src/components/DataGui/Range.vue | 95 +++++++------------ packages/stage/src/components/ThreeDScene.vue | 12 +-- 2 files changed, 39 insertions(+), 68 deletions(-) diff --git a/packages/stage/src/components/DataGui/Range.vue b/packages/stage/src/components/DataGui/Range.vue index 24edad5..84351a0 100644 --- a/packages/stage/src/components/DataGui/Range.vue +++ b/packages/stage/src/components/DataGui/Range.vue @@ -19,57 +19,26 @@ const emit = defineEmits<{ (e: 'mousedown', event: MouseEvent): void }>() +const sliderRef = ref(null) + function clamp(value: number, min: number, max: number): number { return Math.min(Math.max(value, min), max) } -const sliderRef = ref(null) -const isDragging = ref(false) - -// Scale factor for internal calculations -const SCALE_FACTOR = 100 - function getStepPrecision(step: number): number { const stepStr = step.toString() if (stepStr.includes('e-')) { return Number.parseInt(stepStr.split('e-')[1], 10) } + const decimals = stepStr.includes('.') ? stepStr.split('.')[1].length : 0 return decimals } -function scaleUp(value: number): number { - return value * SCALE_FACTOR -} - -function scaleDown(value: number): number { - return value / SCALE_FACTOR -} - function roundToStep(value: number, step: number): number { - const scaledValue = scaleUp(value) - const scaledStep = scaleUp(step) const precision = getStepPrecision(step) - - const rounded = Math.round(scaledValue / scaledStep) * scaledStep - const scaledBack = scaleDown(rounded) - - return Number(scaledBack.toFixed(precision)) -} - -function valueToPercent(value: number, min: number, max: number) { - const scaledValue = scaleUp(value) - const scaledMin = scaleUp(min) - const scaledMax = scaleUp(max) - return ((scaledValue - scaledMin) * 100) / (scaledMax - scaledMin) -} - -function percentToValue(percent: number, min: number, max: number) { - const scaledMin = scaleUp(min) - const scaledMax = scaleUp(max) - const scaledValue = (scaledMax - scaledMin) * percent + scaledMin - const value = scaleDown(scaledValue) - return roundToStep(value, props.step) + const factor = 10 ** (precision + 3) + return Number.parseFloat((value * factor / factor).toFixed(precision)) } const currentValue = computed(() => { @@ -77,10 +46,10 @@ const currentValue = computed(() => { }) const sliderStyle = computed(() => { - const sliderPercent = valueToPercent(currentValue.value, props.min, props.max) + const percent = ((currentValue.value - props.min) / (props.max - props.min)) * 100 return { - width: `${sliderPercent}%`, - backgroundSize: `${sliderPercent}% 100%`, + width: `${percent}%`, + backgroundSize: `${percent}% 100%`, } }) @@ -88,43 +57,48 @@ function getNewValue(event: MouseEvent) { if (!sliderRef.value) return currentValue.value - const { width, left } = sliderRef.value.getBoundingClientRect() - const percent = clamp((event.clientX - left) / width, 0, 1) - return percentToValue(percent, props.min, props.max) + const rect = sliderRef.value.getBoundingClientRect() + const x = event.clientX - rect.left + const percent = x / rect.width + const range = props.max - props.min + const value = props.min + (range * percent) + + // Round to nearest step + const steps = Math.round(value / props.step) * props.step + return Math.min(Math.max(steps, props.min), props.max) } -function handleMouseDown(event: MouseEvent) { +function handleMouseMove(event: MouseEvent) { if (props.disabled) return - event.preventDefault() - isDragging.value = true - emit('mousedown', event) - const newValue = getNewValue(event) emit('update:modelValue', newValue) } -function handleMouseMove(event: MouseEvent) { - if (!isDragging.value || props.disabled) +function handleMouseDown(event: MouseEvent) { + if (props.disabled) return + event.preventDefault() + const newValue = getNewValue(event) emit('update:modelValue', newValue) + + window.addEventListener('mousemove', handleMouseMove) + window.addEventListener('mouseup', handleMouseUp) } function handleMouseUp(_: MouseEvent) { - if (!isDragging.value) - return - - isDragging.value = false + window.removeEventListener('mousemove', handleMouseMove) + window.removeEventListener('mouseup', handleMouseUp) } -function handleMouseLeave(event: MouseEvent) { - if (!isDragging.value) - return - handleMouseUp(event) -} +// Lifecycle hooks +onUnmounted(() => { + window.removeEventListener('mousemove', handleMouseMove) + window.removeEventListener('mouseup', handleMouseUp) +})