vue 的进度条组件
先看效果:
要想实现如上图的,进度跳效果,有两种方式,首先介绍第一种:
1、自己用 div 写一个,代码如下
<template><div class="mfc-slider-runway" ref="runway">
<div class="mfc-slider-bar" :style="{width:w}"></div>
<div class="mfc-slider-button-wrap" :style="{left:w}" ref="thumb">
<div class="mfc-slider-button" ></div>
</div>
</div>
</template>
<script>
//进度条组件
export default{
props:{
min:{ //最小值
type:Number,
default:0
},
max:{ //最大值
type:Number,
default:100
},
step:{ //每步的值为多少
type:Number,
default:1
},
value:{ // v-model 的初始值
type:Number,
default:0
}
},
data(){
return {
startX:0,
moveRun:false,
maxWidth:0,
left:0
};
},
computed:{
w(){
var maxWidth = this.maxWidth ;
if( !maxWidth){
return 0;
}
if(this.min > this.value){
this.value = this.min;
this.$emit("input", this.value);
}
if(this.max < this.value){
this.value = this.max;
this.$emit("input", this.value);
}
var s = ((this.value - this.step - this.min) / (this.max - this.min))*maxWidth; //上限
var e = ((this.value + this.step- this.min ) / (this.max - this.min))*maxWidth; //下限
var left = this.left;
if(left < s || left > e){
//说明value 的值,与 left 容差太大,需要调和,用于外部的 v-model 初始化
console.log("计算容差---");
left = ( (this.value- this.min )/ (this.max - this.min))*maxWidth;
}
return (left / maxWidth)*100 + "%";
}
},
mounted(){
var $thumb = $(this.$refs.thumb);
$thumb.on("mousedown",this.mousedown.bind(this));
$(window).on("mouseup",this.mouseup.bind(this));
this.maxWidth = $(this.$refs.runway).width(); //总共要走的 px 像素
var value = this.value
if(this.min > value){
value = this.min;
}
if(this.max < value){
value = this.max;
}
this.$emit("input", value);
},
methods:{
mousedown(e){
e.preventDefault();
e.stopPropagation();
this.startX = e.clientX ;
this.moveRun = true;
$(window).on("mousemove",this.mousemove.bind(this))
},
mouseup(e){
this.moveRun = false;
$(window).off("mousemove",this.mousemove.bind(this))
},
mousemove(e){
e.preventDefault();
e.stopPropagation();
if(this.moveRun){
var x = e.clientX;
var startX = this.startX;
this.slide(startX,x);
this.startX = x;
}
},
slide(start,end){
var miss = end - start;
if(miss == 0){
return ;
}
var maxWidth = $(this.$refs.runway).width();
if(maxWidth == 0){
return ;
}
var $thumb = $(this.$refs.thumb);
this.offsetLeft = $thumb.offset().left - $thumb.position().left
var left = end - this.offsetLeft;
this.maxWidth = maxWidth;
if(left < 0){
left = 0;
}
if(left > maxWidth){
left = maxWidth;
}
this.left = left;
//----根据 step 的大小,换算出最终的 value 值
var value = (left / maxWidth) * (this.max - this.min) + this.min;
var v = Math.floor(value / this.step);
value = v*this.step + Math.ceil(value - v);
if(this.min > value){
value = this.min;
}
if(this.max < value){
value = this.max;
}
this.$emit("input",value);
}
},
destroyed(){
$(this.$refs.thumb).off("mousedown",this.mousedown.bind(this));
$(window).on("mouseup",this.mouseup.bind(this));
}
}
</script>
<style lang="less">
div.mfc-slider-runway{
width: 100%;
height: 6px;
margin: 10px 0;
background-color: #e4e7ed;
border-radius: 3px;
position: relative;
cursor: pointer;
vertical-align: middle;
div.mfc-slider-bar{
height: 6px;
background-color: #409eff;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
position: absolute;
left: 0;
}
div.mfc-slider-button-wrap{
height: 36px;
width: 36px;
text-align: center;
position: absolute;
z-index: 1001;
top: -15px;
transform: translateX(-50%) ;
background-color: transparent;
text-align: center;
user-select: none;
line-height: normal;
div.mfc-slider-button{
width: 16px;
height: 16px;
border: 2px solid #409eff;
background-color: #fff;
border-radius: 50%;
transition: .2s;
user-select: none;
position: absolute;
left: 0;
right: 0;
top:0;
bottom: 0;
margin: auto;
&:hover{
transform: scale(1.2);
cursor: grab;
}
}
}
}
</style>
使用:
import rangeSlide from "./component/range-slide.vue";<range-slide v-model="test"></range-slide>
<div>
{{test}}
</div>
2、可以使用 input 的新属性 type=range , 然后通过css修改样式
css:
input[type=range] {box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
margin: 0;
padding: 0 2px;
/* Add some L/R padding to ensure box shadow of handle is shown */
overflow: hidden;
border: 0;
border-radius: 1px;
outline: none;
background: -webkit-linear-gradient(#649efd, #649efd) no-repeat center;
background: linear-gradient(#649efd, #649efd) no-repeat center;
/* Use a linear gradient to generate only the 2px height background */
background-size: 100% 2px;
pointer-events: none;
vertical-align: middle;
}
input[type=range]:active,
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-thumb {
height: 18px;
width: 18px;
border-radius: 18px;
background-color: #fff;
position: relative;
margin: 5px 0;
/* Add some margin to ensure box shadow is shown */
cursor: pointer;
-webkit-appearance: none;
appearance: none;
pointer-events: all;
box-shadow: 0 1px 4px 0.5px rgba(0, 0, 0, 0.25);
}
input[type=range]::-webkit-slider-thumb::before {
content: ' ';
display: block;
position: absolute;
top: 13px;
left: 100%;
width: 2000px;
height: 2px;
}
.multi-range {
position: relative;
height: 32px;
}
.multi-range input[type=range] {
position: absolute;
}
.multi-range input[type=range]:nth-child(1)::-webkit-slider-thumb::before {
background-color: red;
}
.multi-range input[type=range]:nth-child(2) {
background: none;
}
.multi-range input[type=range]:nth-child(2)::-webkit-slider-thumb::before {
background-color: grey;
}
使用:
<div class="multi-range"><input type="range">
</div>
小结: 因为 input 的 range属性,兼容不是很好,所以,最好还是自己写,但是自己写会遇见很多坑,比如,value值和step的初始化设置,可能会将 value 设置为一个永远也取不到的值,比如 value初始化为 2 , step又为 5
以上是 vue 的进度条组件 的全部内容, 来源链接: utcz.com/z/377399.html