2.首先此控件采用了vue框架(懒得写原生js)和svg实现。不bb,上代码。使用方法如下。
3.准备好dom
2.引入vue
3.定义vue组件属性如下
props: {
//半径
radius: {
type: Number,
default: 140
},
//最大值
maxValue: {
type: Number,
default: 100
},
//最小值
minValue: {
type: Number,
default: 0
},
//当前值
value: {
type: Number,
default: 50
},
//最大最小值的文本颜色
labelColor: {
type: String,
default: "#535353"
},
//刻度条颜色
activeColor: {
type: String,
default: "#dace01"
},
//刻度条底色
defaultColor: {
type: String,
default: "#666974"
},
//起始角度。采用角度制,未采用弧度制。
startAngle: {
type: Number,
default: 135
},
//终止角度
endAngle: {
type: Number,
default: 405
},
//间隔角度
step: {
type: Number,
default: 5
},
//刻度的长度
strokeWidth: {
type: Number,
default: 20
}
},
4.data属性:
data() {
return {
//刻度线
lines: [],
//当前value对应的角度
currentAngle: 0,
//最大最小值的坐标
label: {
x1: 0,
y1: 0,
x2: 0,
y2: 0
},
timer: null,
isAnimating: false,
i: 0,
//上面的圆形指示器
indicator: {
x: 0,
y: 0,
radius: 5
}
}
},
5.在组件mounted钩子下初始化。
init() {
//起始角度
let startAngle = this.startAngle;
//结束角度
let endAngle = this.endAngle;
//步长
let step = this.step;
//半径
let r1 = this.radius;
//半径2
let r2 = r1 - this.strokeWidth;
//进度
let progress = this.value / (this.maxValue - this.minValue);
let range = endAngle - startAngle;
let currentAngle = range * progress + startAngle;
this.currentAngle = currentAngle;
if (currentAngle < startAngle) {
currentAngle = startAngle
}
if (currentAngle > endAngle) {
currentAngle = endAngle
}
//指示器的x,y坐标 根据圆上的点的坐标公式
// x=centerX + radius*cos(angle) y =centerX + radius*sin(angle)
this.indicator.x = (r1 + (r1 - 5) * Math.cos(currentAngle * Math.PI / 180));
this.indicator.y = (r1 + (r1 - 5) * Math.sin(currentAngle * Math.PI / 180));
//遍历角度,算出每条刻度线的起始坐标和终止坐标。
for (let i = startAngle; i <= endAngle; i += step) {
let color = this.defaultColor;
if (i <= currentAngle) {
color = this.activeColor;
} else {
color = this.defaultColor;
}
let x = (r1 + (r1 - 11) * Math.cos(i * Math.PI / 180));
let y = (r1 + (r1 - 11) * Math.sin(i * Math.PI / 180));
let x2 = (r1 + (r2 - 11) * Math.cos(i * Math.PI / 180));
let y2 = (r1 + (r2 - 11) * Math.sin(i * Math.PI / 180));
this.lines.push({
angle: i,
x1: x,
y1: y,
x2: x2,
y2: y2,
color: color
})
}
this.label.x1 = (r1 + r1 * Math.cos(startAngle * Math.PI / 180));
this.label.y1 = (r1 + r1 * Math.sin(startAngle * Math.PI / 180)) + 20;
this.label.x2 = (r1 + r1 * Math.cos(endAngle * Math.PI / 180)) - 20;
this.label.y2 = (r1 + r1 * Math.sin(endAngle * Math.PI / 180)) + 20;
}
6.动画效果。观察value值变化的时候执行。
startAnimate() {
this.isAnimating = true;
this.lines.forEach(v => {
v.color = this.defaultColor;
});
let self = this;
self.i = 0;
this.indicator.x = (this.radius + (self.radius - 5) * Math.cos(this.startAngle * Math.PI / 180));
this.indicator.y = (this.radius + (self.radius - 5) * Math.sin(this.startAngle * Math.PI / 180));
self.lines[self.i].color = self.activeColor;
if(this.timer){
clearInterval(this.timer);
}
this.timer = setInterval(function () {
self.i++;
if (self.lines.length == self.i) {
self.isAnimating = false;
self.i = 0;
self.clearIn();
return
} else {
if (self.lines[self.i].angle <= self.currentAngle) {
self.indicator.x = (self.radius + (self.radius - 5) * Math.cos(self.lines[self.i].angle * Math.PI / 180));
self.indicator.y = (self.radius + (self.radius - 5) * Math.sin(self.lines[self.i].angle * Math.PI / 180));
self.lines[self.i].color = self.activeColor
} else {
self.lines[self.i].color = self.defaultColor
}
}
}, 100)
},
7.最后完整版代码如下。