- canvas一些api的应用,使用canvas制作低配版echarts 仪表盘组件
具体样式可以自己去跳转调整,只做学习使用,就不再细调了、
<template>
<div class="container" ref="container">
<canvas ref="cvs"></canvas>
</div>
</template>
<script>
export default {
name: 'Canvas',
props: {
option: {
type: Object,
default() {
return {
// 外盘颜色
circleColor: '#000',
// 外盘宽度
circleWidth: 1.5,
// 小分割线长度
smallLine: 5,
// 小分割线颜色
smallLineColor: '#000',
// 大分割线长度
bigLine: 10,
// 大分割线颜色
bigLineColor: '#000',
// 小分割线宽度
smallLineWidth: 1.5,
// 大分割线宽度
bigLineWidth: 3,
// 指针长度 和半径百分比
cursorLength: 0.8,
// 指针颜色
cursorColor: '#f2be45',
// 进度条宽度
progressWidth: 10,
// 进度条颜色
progressColor: 'rgba(255, 173, 0, 0.5)',
// 字体大小
fontSize: 30,
// 展示内容
numberShow: null,
};
},
},
},
data() {
return {
ctx: null,
speedNumber: 0.6,
number: 0.8,
timeout: null,
timer: null,
};
},
watch: {
number: {
handler(newObj, oldObj) {
this.$nextTick(() => {
this.speedNumber = oldObj;
});
},
},
speedNumber: {
handler() {
this.$nextTick(() => {
this.animationDraw();
});
},
},
},
mounted() {
this.drawGuage();
if (!this.timer) {
this.timer = setInterval(() => {
this.number = Number(Math.random().toFixed(2));
}, 4000);
}
},
methods: {
animationDraw() {
console.log(this.number, this.speedNumber);
const temp = this.number - this.speedNumber;
this.timeout = setTimeout(() => {
this.speedNumber = Number((Number(this.speedNumber) + Number(temp / 100)).toFixed(2));
this.drawGuage();
// console.log(Number.valueOf(this.speedNumber), Number.valueOf(this.number));
if (Number.valueOf(this.speedNumber) === Number.valueOf(this.number)) {
clearTimeout(this.timeout);
} else {
this.animationDraw();
}
}, 500);
},
drawGuage() {
if (this.ctx == null) {
this.ctx = this.$refs.cvs.getContext('2d');
}
// console.log(this.$refs.container.clientWidth);
this.$refs.cvs.width = this.$refs.container.clientWidth;
this.$refs.cvs.height = this.$refs.container.clientHeight;
const { width, height } = this.$refs.cvs;
// 半径
const r = width / 2 - 10;
// 外盘颜色
const circleColor = this.option.circleColor == null ? '#000' : this.option.circleColor;
// 外盘宽度
const circleWidth = this.option.circleWidth == null ? 1.5 : this.option.circleWidth;
// 小分割线长度
const smallLine = this.option.smallLine == null ? 5 : this.option.smallLine;
// 小分割线颜色
const smallLineColor = this.option.smallLineColor == null ? '#000' : this.option.smallLineColor;
// 大分割线长度
const bigLine = this.option.bigLine == null ? 10 : this.option.bigLine;
// 大分割线颜色
const bigLineColor = this.option.bigLineColor == null ? '#000' : this.option.bigLineColor;
// 小分割线宽度
const smallLineWidth = this.option.smallLineWidth == null ? 1.5 : this.option.smallLineWidth;
// 大分割线宽度
const bigLineWidth = this.option.bigLineWidth == null ? 3 : this.option.smallLineWidth;
// 指针长度 和半径百分比
const cursorLength = this.option.cursorLength == null ? 0.8 : this.option.cursorLength;
// 指针颜色
const cursorColor = this.option.cursorColor == null ? '#f2be45' : this.option.cursorColor;
// 进度条宽度
const progressWidth = this.option.progressWidth == null ? 10 : this.option.progressWidth;
// 进度条颜色
const progressColor = this.option.progressColor == null ? 'rgba(255, 173, 0, 0.5)' : this.option.progressColor;
// 字体大小
const fontSize = this.option.fontSize == null ? 30 : this.option.fontSize;
// 展示内容
const numberShow = this.option.numberShow == null ? `${Number(this.speedNumber * 100).toFixed(0)}%` : this.option.numberShow;
// 返回上次状态
this.ctx.restore();
// 清除画布,重新画
this.ctx.clearRect(0, 0, width, height);
// 保存画布状态
this.ctx.save();
// 设置原点
this.ctx.translate(width / 2, height / 2);
// 保存状态
this.ctx.save();
// 开始路径
this.ctx.beginPath();
// 画圆盘
this.ctx.lineWidth = circleWidth;
this.ctx.strokeStyle = circleColor;
this.ctx.arc(0, 0, r, 0.75 * Math.PI, 0.25 * Math.PI);
this.ctx.stroke();
// 关闭路径
this.ctx.closePath();
// 画刻度线
this.ctx.rotate(0.75 * Math.PI);
for (let i = 1; i <= 101; i += 1) {
this.ctx.beginPath();
if ((i - 1) % 10 === 0) {
this.ctx.lineWidth = bigLineWidth;
this.ctx.strokeStyle = bigLineColor;
this.ctx.moveTo(r - bigLine, 0);
this.ctx.lineTo(r, 0);
} else {
this.ctx.lineWidth = smallLineWidth;
this.ctx.strokeStyle = smallLineColor;
this.ctx.moveTo(r - smallLine, 0);
this.ctx.lineTo(r, 0);
}
this.ctx.stroke();
this.ctx.closePath();
this.ctx.rotate((1.5 * Math.PI / 100));
}
this.ctx.save();
// 画指针
this.ctx.beginPath();
this.ctx.restore();
this.ctx.rotate(this.speedNumber * 1.5 * Math.PI);
this.ctx.lineCap = 'round';
this.ctx.lineWidth = 2;
this.ctx.moveTo(cursorLength * r * 0.04, cursorLength * r);
this.ctx.lineTo(-cursorLength * r * 0.02, 0);
this.ctx.lineTo(cursorLength * r * 0.02, 0);
this.ctx.lineTo(cursorLength * r * 0.04, cursorLength * r);
this.ctx.strokeStyle = cursorColor;
this.ctx.fillStyle = cursorColor;
this.ctx.fill();
this.ctx.stroke();
this.ctx.closePath();
this.ctx.restore();
// 进度条颜色
this.ctx.strokeStyle = progressColor;
this.ctx.beginPath();
this.ctx.lineWidth = progressWidth;
this.ctx.arc(0, 0, r - (progressWidth / 2), 0.75 * Math.PI, 0.75 * Math.PI + this.speedNumber * 1.5 * Math.PI);
this.ctx.stroke();
this.ctx.closePath();
// 写数值
this.ctx.restore();
this.ctx.font = `${fontSize}px Arial`;
this.ctx.textAlign = 'center';
this.ctx.textBaseline = 'middle';
this.ctx.fillText(`${numberShow}`, width / 2, height / 2 + fontSize);
},
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer);
}
},
};
</script>
<style lang="scss" scoped>
.container {
width: 400px;
height: 400px;
// background: pink;
}
</style>