2020-12-09 21:16:07 +01:00
|
|
|
<template>
|
2022-03-29 01:16:38 +02:00
|
|
|
<label class="slider-wrapper">
|
2022-11-27 00:55:19 +01:00
|
|
|
<span class="range-labels" :class="{'with-label': withLabel}" v-if="withRange">
|
|
|
|
<span class="label left" v-if="withRange" v-text="range[0]" />
|
|
|
|
<span class="label right" v-if="withRange" v-text="range[1]" />
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span class="slider-container">
|
|
|
|
<input class="slider"
|
|
|
|
type="range"
|
|
|
|
:class="{'with-label': withLabel}"
|
|
|
|
:min="range[0]"
|
|
|
|
:max="range[1]"
|
|
|
|
:step="step"
|
|
|
|
:disabled="disabled"
|
|
|
|
:value="value"
|
|
|
|
ref="range"
|
|
|
|
@input.stop="onUpdate"
|
|
|
|
@change.stop="onUpdate">
|
|
|
|
|
|
|
|
<div class="track" :class="{'with-label': withLabel}">
|
|
|
|
<div class="track-inner" ref="track"></div>
|
|
|
|
</div>
|
|
|
|
<div class="thumb" ref="thumb"></div>
|
|
|
|
<span class="label" v-if="withLabel" v-text="value" ref="label"></span>
|
|
|
|
</span>
|
2020-12-09 21:16:07 +01:00
|
|
|
</label>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
export default {
|
|
|
|
name: "Slider",
|
2022-03-29 01:16:38 +02:00
|
|
|
emits: ['input', 'change', 'mouseup', 'mousedown', 'touchstart', 'touchend', 'keyup', 'keydown'],
|
2020-12-09 21:16:07 +01:00
|
|
|
props: {
|
|
|
|
value: {
|
|
|
|
type: Number,
|
|
|
|
},
|
|
|
|
|
|
|
|
disabled: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
|
|
|
|
range: {
|
|
|
|
type: Array,
|
|
|
|
default: () => [0, 100],
|
|
|
|
},
|
2021-02-08 02:04:59 +01:00
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
step: {
|
|
|
|
type: Number,
|
|
|
|
default: 1,
|
|
|
|
},
|
|
|
|
|
2021-02-08 02:04:59 +01:00
|
|
|
withLabel: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
2022-11-27 00:55:19 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
withRange: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
2021-02-08 02:04:59 +01:00
|
|
|
}
|
2020-12-09 21:16:07 +01:00
|
|
|
},
|
2022-03-29 01:16:38 +02:00
|
|
|
|
|
|
|
methods: {
|
|
|
|
onUpdate(event) {
|
|
|
|
this.update(event.target.value)
|
|
|
|
this.$emit(event.type, {
|
|
|
|
...event,
|
|
|
|
target: {
|
|
|
|
...event.target,
|
|
|
|
value: this.$refs.range.value,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
update(value) {
|
2022-10-12 02:59:50 +02:00
|
|
|
const sliderWidth = this.$refs.range.clientWidth
|
|
|
|
const percent = (value - this.range[0]) / (this.range[1] - this.range[0])
|
|
|
|
const innerWidth = percent * sliderWidth
|
|
|
|
const thumb = this.$refs.thumb
|
|
|
|
|
|
|
|
thumb.style.left = `${innerWidth - thumb.clientWidth / 2}px`
|
2022-03-29 01:16:38 +02:00
|
|
|
this.$refs.thumb.style.transform = `translate(-${percent}%, -50%)`
|
2022-10-12 02:59:50 +02:00
|
|
|
this.$refs.track.style.width = `${innerWidth}px`
|
2022-03-29 01:16:38 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
mounted() {
|
|
|
|
if (this.value != null)
|
|
|
|
this.update(this.value)
|
2022-11-27 00:55:19 +01:00
|
|
|
this.$watch(() => this.value, (newValue) => this.update(newValue))
|
2022-03-29 01:16:38 +02:00
|
|
|
},
|
2020-12-09 21:16:07 +01:00
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2022-10-12 02:59:50 +02:00
|
|
|
$label-width: 3em;
|
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
.slider-wrapper {
|
2020-12-09 21:16:07 +01:00
|
|
|
width: 100%;
|
2022-03-29 01:16:38 +02:00
|
|
|
display: flex;
|
|
|
|
position: relative;
|
2022-11-27 00:55:19 +01:00
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.slider-container {
|
|
|
|
width: 100%;
|
|
|
|
display: flex;
|
|
|
|
position: relative;
|
|
|
|
}
|
2020-12-09 21:16:07 +01:00
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
.slider {
|
|
|
|
width: 100%;
|
|
|
|
cursor: pointer;
|
|
|
|
opacity: 0;
|
2020-12-09 21:16:07 +01:00
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
&::-ms-tooltip {
|
|
|
|
display: none;
|
|
|
|
}
|
2020-12-09 21:16:07 +01:00
|
|
|
}
|
|
|
|
|
2022-11-27 00:55:19 +01:00
|
|
|
.range-labels {
|
|
|
|
width: 100%;
|
2023-03-20 01:26:48 +01:00
|
|
|
display: flex;
|
2022-11-27 00:55:19 +01:00
|
|
|
|
|
|
|
&.with-label {
|
|
|
|
width: calc(100% - $label-width);
|
|
|
|
}
|
|
|
|
|
2023-03-20 01:26:48 +01:00
|
|
|
.left {
|
|
|
|
text-align: left;
|
|
|
|
}
|
|
|
|
|
2022-11-27 00:55:19 +01:00
|
|
|
.right {
|
|
|
|
@extend .pull-right;
|
2023-03-20 01:26:48 +01:00
|
|
|
flex-grow: 1;
|
2022-11-27 00:55:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
.track {
|
|
|
|
width: 100%;
|
|
|
|
height: 0.75em;
|
|
|
|
background: $slider-bg;
|
|
|
|
position: absolute;
|
|
|
|
top: 50%;
|
|
|
|
transform: translateY(-50%);
|
|
|
|
border-radius: 0.5em;
|
|
|
|
box-shadow: inset 1px 0px 3px 0 $slider-track-shadow;
|
|
|
|
pointer-events: none;
|
2020-12-09 21:16:07 +01:00
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
.track-inner {
|
|
|
|
width: 0;
|
|
|
|
height: 100%;
|
|
|
|
background: $slider-progress-bg;
|
|
|
|
border-radius: 0.5em 0 0 0.5em;
|
2020-12-14 02:13:55 +01:00
|
|
|
}
|
2022-10-12 02:59:50 +02:00
|
|
|
|
|
|
|
&.with-label {
|
|
|
|
width: calc(100% - $label-width);
|
|
|
|
}
|
2020-12-09 21:16:07 +01:00
|
|
|
}
|
2021-02-08 02:04:59 +01:00
|
|
|
|
2022-03-29 01:16:38 +02:00
|
|
|
.thumb {
|
|
|
|
width: 1.25em;
|
|
|
|
height: 1.25em;
|
|
|
|
background: $slider-thumb-bg;
|
|
|
|
position: absolute;
|
|
|
|
top: 50%;
|
|
|
|
left: 0;
|
|
|
|
transform: translate(0%, -50%);
|
|
|
|
border-radius: 50%;
|
|
|
|
box-shadow: 1px 0px 2px 0 $slider-thumb-shadow;
|
|
|
|
pointer-events: none;
|
|
|
|
}
|
|
|
|
|
2022-10-12 02:59:50 +02:00
|
|
|
.label {
|
|
|
|
width: $label-width;
|
2022-03-29 01:16:38 +02:00
|
|
|
position: relative;
|
2022-10-12 02:59:50 +02:00
|
|
|
font-weight: normal;
|
|
|
|
text-align: center;
|
2021-02-08 02:04:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|