|
|
@@ -1,5 +1,6 @@
|
|
|
<template>
|
|
|
<view class="ruler-wrapper" v-show="visible">
|
|
|
+ <view class="value-bubble" v-if="currentValue !== null">{{ currentValue }}{{ props.unit }}</view>
|
|
|
<scroll-view
|
|
|
class="ruler-scroll"
|
|
|
scroll-x
|
|
|
@@ -15,14 +16,17 @@
|
|
|
v-for="(g, idx) in gridList"
|
|
|
:key="idx"
|
|
|
class="grid-item"
|
|
|
- :class="{ long: g.isLongGrid }"
|
|
|
- :style="{ width: props.gutter + 'px', height: g.showText ? '40px' : '24px' }"
|
|
|
+ :class="{ long: g.isLongGrid, labeled: g.showText }"
|
|
|
+ :style="{ width: props.gutter + 'px' }"
|
|
|
>
|
|
|
+ <view class="tick" :class="{ long: g.isLongGrid }"></view>
|
|
|
<text v-if="g.showText" class="grid-num">{{ g.displayNum }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</scroll-view>
|
|
|
- <view class="indicator"></view>
|
|
|
+ <view class="indicator">
|
|
|
+ <view class="indicator-line"></view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
@@ -48,6 +52,7 @@ const emit = defineEmits(['update:value', 'change'])
|
|
|
const instance = getCurrentInstance()
|
|
|
const scrollLeft = ref(0)
|
|
|
const actualScrollLeft = ref(0)
|
|
|
+const currentValue = ref<number | null>(null)
|
|
|
|
|
|
// prepare grid
|
|
|
const totalUnits = computed(() => Math.round((props.max - props.min) / props.step))
|
|
|
@@ -124,6 +129,7 @@ function onScroll(e: any) {
|
|
|
let value = idx * props.step + props.min
|
|
|
if (value < props.min) value = props.min
|
|
|
if (value > props.max) value = props.max
|
|
|
+ currentValue.value = value
|
|
|
emit('update:value', value)
|
|
|
}
|
|
|
|
|
|
@@ -154,16 +160,22 @@ function onTouchEnd() {
|
|
|
let value = idx * props.step + props.min
|
|
|
if (value < props.min) value = props.min
|
|
|
if (value > props.max) value = props.max
|
|
|
+ currentValue.value = value
|
|
|
emit('change', value)
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
-.ruler-wrapper { position: relative; height: 80rpx; display:flex; align-items:center }
|
|
|
-.ruler-scroll { width: 100%; height: 80rpx }
|
|
|
-.ruler-inner { display:flex; align-items:flex-end }
|
|
|
-.grid-item { width: 10px; height: 24px; display:flex; align-items:flex-end; justify-content:center }
|
|
|
-.grid-item.long { height: 40px }
|
|
|
-.grid-num { font-size: 24rpx; color: #666 }
|
|
|
-.indicator { position: absolute; left: 50%; top: 0; transform: translateX(-50%); width: 2px; height: 100%; background: #ff6a00 }
|
|
|
+.ruler-wrapper { position: relative; height: 90rpx; display:flex; align-items:center; padding-top:20rpx }
|
|
|
+.value-bubble { position: absolute; left: 50%; top: 0; transform: translateX(-50%); background: #ff6a00; color: #fff; padding:6rpx 14rpx; border-radius: 18rpx; font-weight:700; box-shadow: 0 6rpx 18rpx rgba(255,106,0,0.18); z-index: 20 }
|
|
|
+.ruler-scroll { width: 100%; height: 90rpx; overflow: hidden }
|
|
|
+.ruler-inner { display:flex; align-items:flex-end; padding-bottom: 8rpx }
|
|
|
+.grid-item { display:flex; flex-direction:column; align-items:center; justify-content:flex-end; height: 60px; position: relative }
|
|
|
+.grid-item.labeled { height: 80px }
|
|
|
+.tick { width: 2px; background: #ccc; transition: background-color .12s, height .12s }
|
|
|
+.tick.long { height: 34px; background: #999 }
|
|
|
+.grid-item.labeled .grid-num { margin-top:6rpx; color:#333; font-size:24rpx }
|
|
|
+.grid-num { font-size: 20rpx; color: #666 }
|
|
|
+.indicator { position: absolute; left: 50%; top: 18rpx; transform: translateX(-50%); width: 36rpx; height: 54rpx; display:flex; align-items:center; justify-content:center; pointer-events:none }
|
|
|
+.indicator-line { width: 2px; height: 100%; background: #ff6a00; box-shadow: 0 2px 6px rgba(255,106,0,0.25); border-radius:1px }
|
|
|
</style>
|