You've already forked AstralRinth
forked from didirus/AstralRinth
add snappingPoints to slider
This commit is contained in:
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user