需求:滑块进度与输入框为一致,默认值为80,最小不能小于30,最大为100
子组件:
<template>
<div class="progress-box">
<div
ref="slider"
class="slider"
>
<div
class="process"
:style="{ width }"
></div>
<div
ref="trunk"
class="thunk"
:style="{ left }"
>
<div class="block"></div>
</div>
</div>
<div>
<a-input-number
v-model="per"
class="input-num"
:min="inputMin"
:max="inputMax"
@change="handleChangeNum"
/>
</div>
</div>
</template>
<script>
export default {
props: {
sliderMin: { // 最小值
type: Number,
default: 0
},
sliderMax: { // 进度条最大值
type: Number,
default: 0
},
value: { // 对当前值进行双向绑定实时显示拖拽进度
type: Number,
default: 0
},
inputMin: {
type: Number,
default: 0
},
inputMax: {
type: Number,
default: 100
}
},
data() {
return {
slider: null, // 滚动条DOM元素
thunk: null, // 拖拽DOM元素
per: Math.max(this.sliderMin, this.value) // 当前值
}
},
computed: {
// 设置一个百分比,提供计算slider进度宽度和trunk的left值
scale() { // 百分比
return this.per / this.sliderMax
},
width() {
if (this.slider) { // 设置进度激活的宽度
return (this.slider.offsetWidth * this.scale) + 'px'
} else {
return 0 + 'px'
}
},
left() { // trunk left = slider进度width + trunk宽度/2
if (this.slider) { // 设置圆点所在的位置
return (this.slider.offsetWidth * this.scale) - this.thunk.offsetWidth / 2 + 'px'
} else {
return 0 + 'px'
}
}
},
// 渲染到页面的时候
mounted() {
this.slider = this.$refs.slider
this.thunk = this.$refs.trunk
// const _this = this
this.thunk.onmousedown = e => {
const width = parseInt(this.width)
const disX = e.clientX
document.onmousemove = draw => {
// 拖拽的时候获取的新width
const newWidth = (draw.clientX - disX + width)
// 拖拽的时候得到新的百分比
const scale = newWidth / this.slider.offsetWidth
this.per = Math.ceil((this.sliderMax) * scale)// 对一个数进行上取整把小数转为整数(0.3=>30)
this.per = Math.max(this.per, this.sliderMin)
this.per = Math.min(this.per, this.sliderMax)
this.$emit('input', this.per)
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null
}
return false
}
},
methods: {
handleChangeNum(e) {
this.per = e
}
}
}
</script>
<style lang="scss" scoped>
.progress-box {
display: flex;
align-items: center;
justify-content: space-between;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.clear:after {
content: '';
display: block;
clear: both;
}
.slider {
user-select: none;
position: relative;
width: calc(100% - 104px);
height: 4px;
background: #f5f5f5;
border-radius: 5px;
cursor: pointer;
.process {
position: absolute;
left: 0;
top: 0;
width: 112px;
height: 6px;
border-radius: 5px;
background: #3296fa;
}
.thunk {
position: absolute;
left: 100px;
top: -5px;
width: 14px;
height: 14px;
}
.block {
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid #3296fa;
background: rgba(255, 255, 255, 1);
transition: 0.2s all;
}
}
</style>
父组件使用
<div class="xk-control-item">
<div class="xk-item-title">
<span>相似度(≥)</span>
</div>
<div class="xk-item-value">
<c-progress
v-model="per"
:sliderMin="30"
:sliderMax="100"
:inputMin='30'
/>
</div>
</div>
<script>
import CProgress from '@/components/CProgress'
export default {
name: 'VisitorTrack',
components: {
CProgress
},
data() {
return {
}
},
computed: {
per: {
get() {
return 80
},
set(val) {
// console.log(val)
}
}
},
watch: {
},
methods: {
}
}
</script>