159 lines
4.7 KiB
Vue
159 lines
4.7 KiB
Vue
<template>
|
|
<div class="vue3-slider-double">
|
|
<div
|
|
class="slider-bar"
|
|
:style="'left: ' + ( posLeft ) + 'px; width: '
|
|
+ ( 200 - posRight - posLeft ) + 'px;'
|
|
+ 'background-color: ' + $props[ 'barColor' ] + ';'"
|
|
></div>
|
|
<div
|
|
:style="'left: ' + ( posLeft - 5 ) + 'px;'
|
|
+ 'background-color: ' + $props[ 'barColor' ] + ';'"
|
|
class="slider-knob"
|
|
>
|
|
<div
|
|
:class="'drag-support' + ( isDraggingLeft ? ' dragging' : '' )"
|
|
@mousedown="( e ) => { startMove( e.screenX, 'left' ) }"
|
|
@mousemove="( e ) => { handleMove( e.screenX ) }"
|
|
@mouseup="() => endMove()"
|
|
@touchmove="( ev ) => { handleMove( ev.touches[ 0 ]!.screenX ) }"
|
|
@touchstart="( ev ) => { startMove( ev.touches[ 0 ]!.screenX, 'left' ) }"
|
|
@touchend="() => { endMove() }"
|
|
></div>
|
|
</div>
|
|
<div
|
|
:style="'right: ' + ( posRight - 5 ) + 'px;'
|
|
+ 'background-color: ' + $props[ 'barColor' ] + ';'"
|
|
class="slider-knob"
|
|
>
|
|
<div
|
|
:class="'drag-support' + ( isDraggingRight ? ' dragging' : '' )"
|
|
@mousedown="( e ) => { startMove( e.screenX, 'right' ) }"
|
|
@mousemove="( e ) => { handleMove( e.screenX ) }"
|
|
@mouseup="() => { endMove() }"
|
|
@touchmove="( e ) => { handleMove( e.touches[ 0 ]!.screenX ) }"
|
|
@touchstart="( e ) => { startMove( e.touches[ 0 ]!.screenX, 'right' ) }"
|
|
@touchend="() => { endMove() }"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {
|
|
ref
|
|
} from 'vue';
|
|
|
|
const isDraggingLeft = ref( false );
|
|
const isDraggingRight = ref( false );
|
|
const posLeft = ref( 0 );
|
|
|
|
let originalPosLeft = 0;
|
|
|
|
const posRight = ref( 0 );
|
|
|
|
let originalPosRight = 0;
|
|
|
|
const currentlyMoving = ref( '' );
|
|
|
|
let offset = 0;
|
|
|
|
const emits = defineEmits( [ 'interval' ] );
|
|
|
|
const startMove = ( x: number, slider: string ) => {
|
|
currentlyMoving.value = slider;
|
|
offset = x;
|
|
|
|
if ( slider === 'left' ) {
|
|
isDraggingLeft.value = true;
|
|
} else if ( slider === 'right' ) {
|
|
isDraggingRight.value = true;
|
|
}
|
|
};
|
|
|
|
const handleMove = ( x: number ) => {
|
|
if ( currentlyMoving.value === 'right' ) {
|
|
if ( originalPosRight - x + offset >= 0 && originalPosRight - x + offset < 200 - originalPosLeft - 20 ) {
|
|
posRight.value = originalPosRight - x + offset;
|
|
} else if ( originalPosRight - x + offset <= 0 ) {
|
|
posRight.value = 0;
|
|
} else {
|
|
posRight.value = 200 - originalPosLeft - 20;
|
|
}
|
|
|
|
emits( 'interval', [
|
|
posLeft.value / 2,
|
|
( 200 - posRight.value ) / 2
|
|
] );
|
|
} else if ( currentlyMoving.value === 'left' ) {
|
|
if ( x - offset + originalPosLeft >= 0 && x - offset + originalPosLeft < 200 - originalPosRight - 20 ) {
|
|
posLeft.value = x - offset + originalPosLeft;
|
|
} else if ( x - offset + originalPosLeft <= 0 ) {
|
|
posLeft.value = 0;
|
|
} else {
|
|
posLeft.value = 200 - originalPosRight - 20;
|
|
}
|
|
|
|
emits( 'interval', [
|
|
posLeft.value / 2,
|
|
( 200 - posRight.value ) / 2
|
|
] );
|
|
}
|
|
};
|
|
|
|
const endMove = () => {
|
|
currentlyMoving.value = '';
|
|
isDraggingLeft.value = false;
|
|
isDraggingRight.value = false;
|
|
originalPosLeft = posLeft.value;
|
|
originalPosRight = posRight.value;
|
|
};
|
|
|
|
defineProps<{
|
|
'handleColor': string,
|
|
'barColor': string
|
|
}>();
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
.vue3-slider-double {
|
|
position: relative;
|
|
width: 200px;
|
|
height: 10px;
|
|
border: black solid 1px;
|
|
border-radius: 50px;
|
|
}
|
|
|
|
.vue3-slider-double .slider-knob {
|
|
position: absolute;
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50px;
|
|
top: -5px;
|
|
}
|
|
|
|
.vue3-slider-double .drag-support {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50px;
|
|
background: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.vue3-slider-double .drag-support.dragging {
|
|
position: fixed;
|
|
cursor: move;
|
|
top: 0;
|
|
left: 0;
|
|
height: 100vh;
|
|
width: 100vw;
|
|
}
|
|
|
|
.vue3-slider-double .slider-bar {
|
|
position: absolute;
|
|
background-color: var( --hover-color );
|
|
height: 10px;
|
|
}
|
|
</style>
|