Quellcode durchsuchen

feat(scale-ruler): 支持小数步长的刻度尺组件

- 新增 decimalPlaces 函数计算数字的小数位数
- 引入 scaleFactor 将小数步长映射到整数空间进行计算
- 修改 totalUnits 计算逻辑以适配小数步长
- 更新网格构建逻辑,确保显示正确的数值和长刻度标记
- 调整初始化索引和值的计算方式以支持小数精度
- 修改滚动和触摸结束时的值计算逻辑以保持精度
- 确保所有数值输出都保留正确的小数位数
mcbaiyun vor 2 Monaten
Ursprung
Commit
971049a8e8
1 geänderte Dateien mit 38 neuen und 15 gelöschten Zeilen
  1. 38 15
      src/components/scale-ruler.vue

+ 38 - 15
src/components/scale-ruler.vue

@@ -45,7 +45,24 @@ const actualScrollLeft = ref(0)
 const currentValue = ref(Math.round(props.initialValue || props.min))
 
 
-const totalUnits = computed(() => Math.round((props.max - props.min) / props.step))
+// Support decimal step: convert to integer space using scale factor
+function decimalPlaces(n: number) {
+  const s = String(n)
+  if (s.indexOf('e-') >= 0) {
+    const m = s.match(/e-(\d+)$/)
+    return m ? parseInt(m[1], 10) : 0
+  }
+  const idx = s.indexOf('.')
+  return idx >= 0 ? s.length - idx - 1 : 0
+}
+
+const stepDecimals = decimalPlaces(props.step)
+const scaleFactor = Math.pow(10, stepDecimals)
+const intMin = Math.round(props.min * scaleFactor)
+const intMax = Math.round(props.max * scaleFactor)
+const intStep = Math.round(props.step * scaleFactor)
+
+const totalUnits = computed(() => Math.round((intMax - intMin) / intStep))
 
 
 const extraGridCount = Math.ceil((uni?.getSystemInfoSync?.().windowWidth || 375) / props.gutter / 2) * 2
@@ -60,9 +77,11 @@ function buildGrid() {
   const arr: GridItem[] = []
   for (let i = 0; i <= count + extraGridCount * 1; i++) {
     const numIndex = i - extraGridCount / 2
-    const num = props.min + numIndex * props.step
-    const displayNum = num
-    const isLongGrid = (numIndex % 10 === 0)
+    const intNum = intMin + numIndex * intStep
+    const num = intNum / scaleFactor
+    const displayNum = (Number.isInteger(num) ? num : Number(num.toFixed(stepDecimals)))
+    // mark long grid every 10 steps in integer space (10 * intStep)
+    const isLongGrid = ((intNum - intMin) % (intStep * 10) === 0)
     const showText = isLongGrid && num >= props.min && num <= props.max
     arr.push({ num, displayNum, isLongGrid, showText })
   }
@@ -80,7 +99,11 @@ const halfWindow = windowWidth / 2
 
 onMounted(() => {
 
-  const initIndex = Math.round((props.initialValue - props.min) / props.step)
+  // initialize using integer index space
+  const initIndex = Math.round((Math.round((props.initialValue || props.min) * scaleFactor) - intMin) / intStep)
+  scrollLeft.value = offsetScroll.value + initIndex * props.gutter + props.gutter / 2 - halfWindow
+  const initVal = (intMin + initIndex * intStep) / scaleFactor
+  currentValue.value = Number(stepDecimals ? initVal.toFixed(stepDecimals) : String(initVal))
 
   scrollLeft.value = offsetScroll.value + initIndex * props.gutter + props.gutter / 2 - halfWindow
 
@@ -92,11 +115,11 @@ function onScroll(e: any) {
   actualScrollLeft.value = left
 
   const numIndex = Math.round((left + halfWindow - offsetScroll.value - props.gutter / 2) / props.gutter)
-  let value = numIndex * props.step + props.min
-  if (value < props.min) value = props.min
-  if (value > props.max) value = props.max
-
-  currentValue.value = Math.round(value)
+  let intValue = intMin + numIndex * intStep
+  if (intValue < intMin) intValue = intMin
+  if (intValue > intMax) intValue = intMax
+  const value = intValue / scaleFactor
+  currentValue.value = Number(stepDecimals ? value.toFixed(stepDecimals) : String(value))
   emit('update:value', value)
 }
 
@@ -119,11 +142,11 @@ function onTouchEnd() {
 
   const left = scrollLeft.value
   const numIndex = Math.round((left + halfWindow - offsetScroll.value - props.gutter / 2) / props.gutter)
-  let value = numIndex * props.step + props.min
-  if (value < props.min) value = props.min
-  if (value > props.max) value = props.max
-
-  currentValue.value = Math.round(value)
+  let intValue = intMin + numIndex * intStep
+  if (intValue < intMin) intValue = intMin
+  if (intValue > intMax) intValue = intMax
+  const value = intValue / scaleFactor
+  currentValue.value = Number(stepDecimals ? value.toFixed(stepDecimals) : String(value))
   emit('change', value)
 }
 </script>