<template>
<div
class="process-bar-outer"
ref="outer"
:style="outerStyle"
@mousedown="handleOuter">
<div class="process-bar-inner" :style="innerStyle"></div>
<div class="process-bar-slider" :style="sliderStyle"></div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref,defineProps, defineEmits, computed, onUnmounted } from "vue";
const props = defineProps({
modelValue: {
type: Number,
default: 0
},
width: {
type: Number,
default: 200
},
height: {
type: Number,
default: 6
},
sliderWidth: {
type: Number,
default: 10
}
})
const emit = defineEmits(['update:modelValue'])
const currPos = ref(Math.round(props.width * props.modelValue / 100));
const space = (props.sliderWidth - props.height) / 2;
let outerOffsetLeft: number;
let outer = ref(null);
let sliding = false;
const outerStyle = {
width: props.width + 'px',
height: props.height + 'px',
borderRadius: props.height + 'px'
}
const innerStyle = computed(() => {
return {
width: currPos.value + 'px',
borderRadius: props.height + 'px'
}
})
const sliderStyle = computed(() => {
return {
width: props.sliderWidth + 'px',
height: props.sliderWidth + 'px',
top: -space + 'px',
left: currPos.value - (props.sliderWidth / 2) + 'px'
}
})
const handleOuter = (e: MouseEvent) => {
sliding = true;
currPos.value = handleBoundary(e.clientX - outerOffsetLeft)
}
const handleBoundary = (value: number) => {
value = Math.min(props.width, value);
value = Math.max(0, value);
emit('update:modelValue', Math.round(value / props.width * 100))
return value;
}
const handlMousemove = (e:MouseEvent) => {
if (sliding) {
currPos.value = handleBoundary(e.clientX - outerOffsetLeft)
}
}
const handlMouseup = (e:MouseEvent) => {
sliding = false;
currPos.value = handleBoundary(e.clientX - outerOffsetLeft)
}
onMounted(() => {
outerOffsetLeft = (outer.value as any).getBoundingClientRect().left;
document.addEventListener('mousemove', handlMousemove)
document.addEventListener('mouseup', handlMouseup)
})
onUnmounted(() => {
document.removeEventListener('mousemove', handlMousemove)
document.removeEventListener('mouseup', handlMouseup)
})
</script>
<style lang="scss" scoped>
div {
box-sizing: border-box;
}
.process-bar-outer {
caret-color: rgba(0,0,0,0);
position: relative;
background-color: #ebeef5;
.process-bar-inner {
height: 100%;
background-color: #409eff;
}
.process-bar-slider {
position: absolute;
border-radius: 50%;
border: 1.6px solid #409EFF;
background-color: #ffffff;
}
}
</style>