Skip to content

Commit

Permalink
fix: smooth issue
Browse files Browse the repository at this point in the history
  • Loading branch information
nekomeowww committed Dec 4, 2024
1 parent 5738c21 commit 4aa1de9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 68 deletions.
95 changes: 33 additions & 62 deletions packages/stage/src/components/DataGui/Range.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,112 +19,86 @@ const emit = defineEmits<{
(e: 'mousedown', event: MouseEvent): void
}>()
const sliderRef = ref<HTMLElement | null>(null)
function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max)
}
const sliderRef = ref<HTMLElement | null>(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(() => {
return roundToStep(clamp(props.modelValue, props.min, props.max), props.step)
})
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%`,
}
})
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)
})
</script>

<template>
Expand All @@ -134,15 +108,12 @@ function handleMouseLeave(event: MouseEvent) {
:class="{ disabled }"
bg="[#e6e1fc] dark:[#676085]" touch-action-none relative inline-block w-full cursor-ew-resize rounded-sm
@mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@mouseleave="handleMouseLeave"
>
<span :style="sliderStyle" bg="[#cabeff] dark:[#4e34b9]" relative block rounded-sm h="[14px]" />
<span
role="slider"
class="slider-thumb"
:style="{ left: `${valueToPercent(currentValue, min, max)}%` }"
:style="{ left: `${((currentValue - min) / (max - min)) * 100}%` }"
absolute rounded-sm w="[1px]" h="[14px]" bg="zinc-100 dark:zinc-400" top="50%" transform="translate-x-[50%] translate-y-[-50%]"
/>
</span>
Expand Down
12 changes: 6 additions & 6 deletions packages/stage/src/components/ThreeDScene.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const vrmModelPositionZ = ref(-0.3)
<label w-full flex items-center gap-2>
<DataGuiRange v-model="cameraPositionX" :min="-10" :max="10" :step="0.01" />
</label>
<div>
<div text-right>
<span>{{ cameraPositionX }}</span>
</div>

Expand All @@ -47,7 +47,7 @@ const vrmModelPositionZ = ref(-0.3)
<label w-full flex items-center gap-2>
<DataGuiRange v-model="cameraPositionY" :min="-10" :max="10" :step="0.01" />
</label>
<div>
<div text-right>
<span>{{ cameraPositionY }}</span>
</div>

Expand All @@ -57,7 +57,7 @@ const vrmModelPositionZ = ref(-0.3)
<label w-full flex items-center gap-2>
<DataGuiRange v-model="cameraPositionZ" :min="-10" :max="10" :step="0.01" />
</label>
<div>
<div text-right>
<span>{{ cameraPositionZ }}</span>
</div>
</div>
Expand All @@ -74,7 +74,7 @@ const vrmModelPositionZ = ref(-0.3)
<label w-full flex items-center gap-2>
<DataGuiRange v-model="vrmModelPositionX" :min="-10" :max="10" :step="0.01" />
</label>
<div>
<div text-right>
<span>{{ vrmModelPositionX }}</span>
</div>

Expand All @@ -84,7 +84,7 @@ const vrmModelPositionZ = ref(-0.3)
<label w-full flex items-center gap-2>
<DataGuiRange v-model="vrmModelPositionY" :min="-10" :max="10" :step="0.01" />
</label>
<div>
<div text-right>
<span>{{ vrmModelPositionY }}</span>
</div>

Expand All @@ -94,7 +94,7 @@ const vrmModelPositionZ = ref(-0.3)
<label w-full flex items-center gap-2>
<DataGuiRange v-model="vrmModelPositionZ" :min="-10" :max="10" :step="0.01" />
</label>
<div>
<div text-right>
<span>{{ vrmModelPositionZ }}</span>
</div>
</div>
Expand Down

0 comments on commit 4aa1de9

Please sign in to comment.