vue绘制canvas绘制双圆环进度池组件
canvas绘制双圆环进度池
组件代码
<template>
<canvas
ref="circle"
moz-opaque
:width="width"
:height="height"
:BigColor="BigColor"
:contentData="contentData"
:allData="allData"
:contentStyle="contentStyle"
:SmallColor="SmallColor"
:SmallRadius="SmallRadius"
:InsideRadius="InsideRadius"
:lineGrad="lineGrad"
:contentGrad="contentGrad"
:title="title"
></canvas>
</template>
<script>
export default {
name: 'CanvasCircle',
props:{
width: {
type: Number,
require: true
},
height: {
type: Number,
require: true
},
BigColor: {
type: String,
default: '#013967'
},
contentData: {
type: Number,
require: true
},
allData: {
type: Number,
default: 100
},
contentStyle: {
type: Object,
default(){
return {
0: '#01D9FE',
1: '#0477D5'
}
}
},
SmallColor: {
type: String,
default: '#013967'
},
SmallRadius: {
type: Number,
require: true
},
InsideRadius: {
type: Number,
require: true
},
lineGrad: {
type: Object,
default(){
return {
direction: 'ToRight',
style: {
0: '#03D5FB',
1: '#2068C0'
}
}
}
},
contentGrad: {
type: Object,
default(){
return {
direction: 'ToTop',
style: {
0: '#025289',
1: '#02193F'
}
}
}
},
title: {
type: Object,
default(){
return {
}
}
}
},
methods: {
AngleFn(data){
let startAngle = Math.PI / 180 * (90 - (data / this.allData * 360 / 2));
let endAngle = Math.PI / 180 * (90 + (data / this.allData * 360 / 2));
return {
startAngle,
endAngle
}
}
},
mounted(){
let canvasBox = this.$refs.circle;
let ctx = canvasBox.getContext('2d');
//fillRect(x, y, width, height)绘制一个填充的矩形
//strokeRect(x, y, width, height)绘制一个矩形的边框
//clearRect(x, y, width, height)清除指定矩形区域
//beginPath() 新建一条路径
//closePath() 闭合路径
//stroke() 通过该线条来绘制图形轮廓
//fill()通过填充路径的内容区域生成实心的图形
//moveTo(x, y) 将笔触移动到指定的坐标x,y上
//lineTo(x, y) 绘制从当前位置到指定x,y 的直线
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
@params
width-----------canvas宽度
height----------canvas高度
BigColor-------最外层圆颜色
allData--------总数量
contentData----内容大小(进度池容量)
contentStyle----进度池样式
SmallColor------中层圆样式
SmallRadius----中层圆半径
InsideRadius-----最里层圆的半径
lineGrad----------最里层圆边框样式
contentGrad----最里层圆样式
title----------------文本
+++++++++++++++++++++++++++++++++++++++++++++++++++++*/
let bigCircle = new Path2D();
bigCircle.arc(this.width / 2, this.height / 2, this.width / 2, 0, Math.PI * 2);
let contentCircle = new Path2D();
contentCircle.arc(this.width / 2, this.height / 2, this.width / 2, this.AngleFn(this.contentData).startAngle, this.AngleFn(this.contentData).endAngle);
// let leftX, leftY, rightX, rightY;
// let percentage = this.contentData / this.allData;
// let contentY = this.height * percentage;
// if( this.height / 2 - this.SmallRadius < contentY < this.height - (this.height / 2 - this.SmallRadius) ){
// if(percentage < 0.5){
// leftY = rightY = this.height * (1 - percentage);
// let x = Math.sqrt(this.SmallRadius ** 2 - (this.height / 2 - this.height * percentage) ** 2);
// leftX = this.width / 2 - x;
// rightX = this.width / 2 + x;
// //contentCircle.moveTo(leftX, leftY);
// contentCircle.arc(this.width / 2, this.height / 2, this.SmallRadius, this.AngleFn(this.contentData).endAngle, this.AngleFn(this.contentData).startAngle, true);
// console.log(rightY, rightX, leftY, leftX)
// }
// }
let smallCircle = new Path2D();
smallCircle.arc(this.width / 2, this.height / 2, this.SmallRadius, 0, Math.PI * 2);
ctx.strokeStyle = this.BigColor;
ctx.stroke(bigCircle);
let contentColor = ctx.createLinearGradient(this.width / 2, this.height, this.width / 2, this.height * (1 - this.contentData / this.allData));
for(let key in this.contentStyle){
contentColor.addColorStop(key, this.contentStyle[key]);
}
ctx.fillStyle = contentColor;
ctx.fill(contentCircle);
ctx.fillStyle = '#000A3B';
ctx.fill(smallCircle);
ctx.strokeStyle = this.SmallColor;
ctx.stroke(smallCircle);
let insideCircle = new Path2D();
insideCircle.arc(this.width/ 2, this.height / 2, this.InsideRadius, 0, Math.PI * 2);
let lineGrad = this.lineGrad.direction == 'ToTop'
?
ctx.createLinearGradient(this.width / 2, this.height / 2 + this.InsideRadius, this.width / 2, this.height / 2 - this.InsideRadius)
:
ctx.createLinearGradient(this.width / 2 - this.InsideRadius, this.height / 2, this.width / 2 + this.InsideRadius, this.height / 2);
for(let key in this.lineGrad.style){
lineGrad.addColorStop(key, this.lineGrad.style[key]);
}
let gradColor = this.contentGrad.direction == 'ToTop'
?
ctx.createLinearGradient(this.width / 2, this.height / 2 + this.InsideRadius, this.width / 2, this.height / 2 - this.InsideRadius)
:
ctx.createLinearGradient(this.width / 2 - this.InsideRadius, this.height / 2, this.width / 2 + this.InsideRadius, this.height / 2);
for(let key in this.contentGrad.style){
gradColor.addColorStop(key, this.contentGrad.style[key]);
}
ctx.fillStyle = gradColor;
ctx.fill(insideCircle);
ctx.strokeStyle = lineGrad;
ctx.stroke(insideCircle);
ctx.font = this.title.font;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = this.title.color;
ctx.fillText(this.title.text, this.width / 2, this.height / 2);
}
}
</script>
##父组件代码
<canvas-circle
:width="120"
:height="120"
:contentData="30"
:allData="100"
:SmallRadius="55"
:InsideRadius="50"
:title="{text: '352.33亿', font : '0.2rem SourceHanSansCN-Bold', color: '#02D9FD'}"
/>