add snappingPoints to slider
This commit is contained in:
parent
ae7f7e9bd6
commit
3955b973ef
@ -9,6 +9,7 @@ const valueTwo = ref(0)
|
||||
|
||||
<DemoContainer>
|
||||
<Slider v-model="value" :min="1000" :max="10000" :step="1000" unit="mb"/>
|
||||
<Slider v-model="value" :min="1024" :max="32768" :step="1" :snapPoints='[2048,4096,8192,16384]' :snapRange='500' unit="mb"/>
|
||||
<Slider v-model="valueTwo" :min="1000" :max="10000" :step="1000" unit="mb" :disabled="true"/>
|
||||
</DemoContainer>
|
||||
|
||||
|
||||
@ -2,6 +2,15 @@
|
||||
<div class="root-container">
|
||||
<div class="slider-component">
|
||||
<div class="slide-container">
|
||||
<div class="snap-points">
|
||||
<div
|
||||
class="snap-point"
|
||||
:class="{ green: snapPoint <= currentValue }"
|
||||
v-for="snapPoint in props.snapPoints"
|
||||
v-bind:key="snapPoint"
|
||||
:style="{ left: ((snapPoint - props.min) / (props.max - props.min)) * 100 + '%' }"
|
||||
></div>
|
||||
</div>
|
||||
<input
|
||||
ref="input"
|
||||
v-model="currentValue"
|
||||
@ -19,7 +28,7 @@
|
||||
'--min-value': min,
|
||||
'--max-value': max,
|
||||
}"
|
||||
@input="onInput($refs.input.value)"
|
||||
@input="onInputWithSnap($refs.input.value)"
|
||||
/>
|
||||
<div class="slider-range">
|
||||
<span> {{ min }} {{ unit }} </span>
|
||||
@ -64,6 +73,14 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
snapPoints: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
snapRange: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@ -88,9 +105,24 @@ const inputValueValid = (newValue) => {
|
||||
} else {
|
||||
currentValue.value = (parsedValue - (props.forceStep ? parsedValue % props.step : 0)).toString()
|
||||
}
|
||||
|
||||
emit('update:modelValue', parseInt(currentValue.value))
|
||||
}
|
||||
|
||||
const onInputWithSnap = (value) => {
|
||||
let parsedValue = parseInt(value)
|
||||
|
||||
for (let snapPoint of props.snapPoints) {
|
||||
const distance = Math.abs(snapPoint - parsedValue)
|
||||
|
||||
if (distance < props.snapRange) {
|
||||
parsedValue = snapPoint
|
||||
}
|
||||
}
|
||||
|
||||
inputValueValid(parsedValue)
|
||||
}
|
||||
|
||||
const onInput = (value) => {
|
||||
inputValueValid(value)
|
||||
}
|
||||
@ -111,11 +143,15 @@ const onInput = (value) => {
|
||||
.slider-component,
|
||||
.slide-container {
|
||||
width: 100%;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.slider-component .slide-container .slider {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
position: relative;
|
||||
|
||||
border-radius: var(--radius-sm);
|
||||
height: 0.25rem;
|
||||
background: linear-gradient(
|
||||
@ -144,6 +180,7 @@ const onInput = (value) => {
|
||||
}
|
||||
|
||||
.slider-component .slide-container .slider::-moz-range-thumb {
|
||||
border: none;
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
background: var(--color-brand);
|
||||
@ -164,6 +201,29 @@ const onInput = (value) => {
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.slider-component .slide-container .snap-points {
|
||||
position: absolute;
|
||||
width: calc(100% - 0.75rem);
|
||||
left: calc(0.75rem / 2);
|
||||
top: calc(1rem / 2);
|
||||
|
||||
.snap-point {
|
||||
position: absolute;
|
||||
|
||||
width: 0.25rem;
|
||||
height: 0.75rem;
|
||||
border-radius: var(--radius-sm);
|
||||
|
||||
background-color: var(--color-base);
|
||||
|
||||
transform: translateX(calc(-0.25rem / 2));
|
||||
|
||||
&.green {
|
||||
background-color: var(--color-brand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slider-input {
|
||||
width: 6rem;
|
||||
margin-left: 0.75rem;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user