add snappingPoints to slider

This commit is contained in:
tobinio
2023-10-08 10:49:51 +02:00
parent ae7f7e9bd6
commit 3955b973ef
2 changed files with 62 additions and 1 deletions

View File

@@ -9,6 +9,7 @@ const valueTwo = ref(0)
<DemoContainer> <DemoContainer>
<Slider v-model="value" :min="1000" :max="10000" :step="1000" unit="mb"/> <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"/> <Slider v-model="valueTwo" :min="1000" :max="10000" :step="1000" unit="mb" :disabled="true"/>
</DemoContainer> </DemoContainer>

View File

@@ -2,6 +2,15 @@
<div class="root-container"> <div class="root-container">
<div class="slider-component"> <div class="slider-component">
<div class="slide-container"> <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 <input
ref="input" ref="input"
v-model="currentValue" v-model="currentValue"
@@ -19,7 +28,7 @@
'--min-value': min, '--min-value': min,
'--max-value': max, '--max-value': max,
}" }"
@input="onInput($refs.input.value)" @input="onInputWithSnap($refs.input.value)"
/> />
<div class="slider-range"> <div class="slider-range">
<span> {{ min }} {{ unit }} </span> <span> {{ min }} {{ unit }} </span>
@@ -64,6 +73,14 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
snapPoints: {
type: Array,
default: () => [],
},
snapRange: {
type: Number,
default: 100,
},
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false, default: false,
@@ -88,9 +105,24 @@ const inputValueValid = (newValue) => {
} else { } else {
currentValue.value = (parsedValue - (props.forceStep ? parsedValue % props.step : 0)).toString() currentValue.value = (parsedValue - (props.forceStep ? parsedValue % props.step : 0)).toString()
} }
emit('update:modelValue', parseInt(currentValue.value)) 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) => { const onInput = (value) => {
inputValueValid(value) inputValueValid(value)
} }
@@ -111,11 +143,15 @@ const onInput = (value) => {
.slider-component, .slider-component,
.slide-container { .slide-container {
width: 100%; width: 100%;
position: relative;
} }
.slider-component .slide-container .slider { .slider-component .slide-container .slider {
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
position: relative;
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
height: 0.25rem; height: 0.25rem;
background: linear-gradient( background: linear-gradient(
@@ -144,6 +180,7 @@ const onInput = (value) => {
} }
.slider-component .slide-container .slider::-moz-range-thumb { .slider-component .slide-container .slider::-moz-range-thumb {
border: none;
width: 0.75rem; width: 0.75rem;
height: 0.75rem; height: 0.75rem;
background: var(--color-brand); background: var(--color-brand);
@@ -164,6 +201,29 @@ const onInput = (value) => {
transition: 0.2s; 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 { .slider-input {
width: 6rem; width: 6rem;
margin-left: 0.75rem; margin-left: 0.75rem;