环图
canvas制作圆形所用的方法是
ctx.arc(x,y,r,0,Math,PI*2,false)
其中的6个参数分别是圆心横坐标,圆心纵坐标,半径,起始角度,结束角度,false顺势针/true逆时针 而圆环也是用的这个方法,只不过是ctx.fill()填充,替换成了ctx.stroke()描边,利用描边我们就可以绘制出任何大小及弧度的圆环了,通过ctx.linewidth可以设置描边的粗细,也就是圆环的宽窄。 上图中其实是个统计用的图表,展示的是四个数据在这个圆环中的占比情况。由于canvas采用的是帧绘制,所以在有轮流高亮的情况下,就是定时的清除画布然后重绘,清除画布的方法是 ctx.clearRect(起始x,起始y,结束x,结束y)
图一
图一JS
function gague(arr
, index
) {
var canvas
= document
.querySelector('#cav')
var cav
= canvas
.getContext('2d');
cav
.clearRect(0, 0, 300, 300);
var wholeCircle
= Math
.PI * 2
var wholeAngle
= wholeCircle
* 3 / 4
var sum
= eval(arr
.join('+'))
var startAngle
= wholeCircle
* 3 / 8 + wholeCircle
/ 200
var endAngle
= startAngle
+ wholeAngle
* (arr
[0] / sum
) - wholeCircle
/ 100
cav
.beginPath()
cav
.lineWidth
= 40
cav
.strokeStyle
= 'rgb(56,64,129)';
cav
.arc(150, 150, 90, startAngle
- wholeCircle
/ 200, startAngle
, false)
cav
.stroke()
for (let i
= 0; i
< arr
.length
; i
++) {
var PointAssemble
= getPoint(startAngle
, endAngle
, 110, 150, 150)
var normalColor
= cav
.createLinearGradient(PointAssemble
.startPointX
, PointAssemble
.startPointY
, PointAssemble
.endPointX
, PointAssemble
.endPointY
);
normalColor
.addColorStop(0, "rgba(68,102,244,0.2)");
normalColor
.addColorStop(1, 'rgba(68,102,244,0.4)');
var highlightColor
= cav
.createLinearGradient(PointAssemble
.startPointX
, PointAssemble
.startPointY
,
PointAssemble
.endPointX
, PointAssemble
.endPointY
);
highlightColor
.addColorStop(0, "rgba(56,64,129,0.2)");
highlightColor
.addColorStop(1, 'rgba(255,15,110,0.6)');
cav
.beginPath()
cav
.lineWidth
= 40
cav
.strokeStyle
= index
== i
? highlightColor
: normalColor
;
cav
.arc(150, 150, 90, startAngle
, endAngle
, false)
cav
.stroke()
cav
.beginPath()
cav
.lineWidth
= 40
cav
.strokeStyle
= index
== i
? 'rgb(255,15,110)' : 'rgb(68,102,244)';
cav
.arc(150, 150, 90, endAngle
, endAngle
+ wholeCircle
/ 100, false)
cav
.stroke()
startAngle
= startAngle
+ wholeAngle
* (arr
[i
] / sum
)
endAngle
= startAngle
+ wholeAngle
* (arr
[i
+ 1] / sum
) - wholeCircle
/ 100
}
}
图二
上图的高亮处小圆点是个图片,要注意的是,如果canvas中出现图片,要先获取图片,等图片加载完毕之后再调用canvas的绘图方法
var img
= new Image()
img
.src
='图片路径'
img
.onload =()=>{
}
图二JS
function halfCircle(arr
, index
) {
var canvas
= document
.querySelector('#cav4')
var cav
= canvas
.getContext('2d');
cav
.clearRect(0, 0, 300, 300);
var wholeCircle
= Math
.PI * 2
var wholeAngle
= wholeCircle
/ 2
var sum
= eval(arr
.join('+'))
var startAngle
= wholeCircle
/ 2
var endAngle
= startAngle
+ wholeAngle
* (arr
[0] / sum
)
for (let i
= 0; i
< arr
.length
; i
++) {
var PointAssemble
= getPoint(startAngle
, endAngle
, 90, 150, 150)
var normalColor
= cav
.createLinearGradient(PointAssemble
.startPointX
, PointAssemble
.startPointY
, PointAssemble
.endPointX
, PointAssemble
.endPointY
);
normalColor
.addColorStop(0, "rgba(9, 9, 24,0)");
normalColor
.addColorStop(1, 'rgba(42, 81, 248,1)');
var highlightColor
= cav
.createLinearGradient(PointAssemble
.startPointX
, PointAssemble
.startPointY
,
PointAssemble
.endPointX
, PointAssemble
.endPointY
);
highlightColor
.addColorStop(0, "rgba(29, 11, 35,0)");
highlightColor
.addColorStop(1, 'rgba(228, 90, 147,1)');
cav
.beginPath()
cav
.lineWidth
= 10
cav
.strokeStyle
= index
== i
? highlightColor
: normalColor
;
cav
.lineCap
= 'round'
cav
.arc(150, 150, 90, startAngle
, endAngle
, false)
cav
.stroke()
if (i
== index
) {
cav
.drawImage(imgYuan
, PointAssemble
.endPointX
- imgYuan
.width
/ 2, PointAssemble
.endPointY
- imgYuan
.height
/ 2)
}
startAngle
= startAngle
+ wholeAngle
* (arr
[i
] / sum
)
endAngle
= startAngle
+ wholeAngle
* (arr
[i
+ 1] / sum
)
}
}
值得注意的一点是,当你的圆环半径确定的时候,不管你的圆环宽度有多宽,圆环的半径始终是从圆心到二分之一圆环宽度的距离,而不是从圆心到圆环外边或者到圆环内边的距离,所以你的圆环越宽,他的实际面积会越大
自定义获取坐标点函数
function getPoint(startAngle
, endAngle
, r
, circleX
, circleY
) {
var startPointX
, startPointY
, endPointX
, endPointY
if (startAngle
< Math
.PI) {
startPointX
= circleX
- Math
.sin(startAngle
- Math
.PI / 2) * r
startPointY
= circleY
+ Math
.cos(startAngle
- Math
.PI / 2) * r
} else if (startAngle
< Math
.PI * 3 / 2) {
startPointX
= circleX
- Math
.cos(startAngle
- Math
.PI) * r
startPointY
= circleY
- Math
.sin(startAngle
- Math
.PI) * r
} else if (startAngle
< Math
.PI * 2) {
startPointX
= circleX
+ Math
.sin(startAngle
- Math
.PI * 3 / 2) * r
startPointY
= circleY
- Math
.cos(startAngle
- Math
.PI * 3 / 2) * r
} else {
startPointX
= circleX
+ Math
.cos(startAngle
- Math
.PI * 2) * r
startPointY
= circleY
+ Math
.sin(startAngle
- Math
.PI * 2) * r
}
if (endAngle
< Math
.PI) {
endPointX
= circleX
- Math
.sin(endAngle
- Math
.PI / 2) * r
endPointY
= circleY
+ Math
.cos(endAngle
- Math
.PI / 2) * r
} else if (endAngle
< Math
.PI * 3 / 2) {
endPointX
= circleX
- Math
.cos(endAngle
- Math
.PI) * r
endPointY
= circleY
- Math
.sin(endAngle
- Math
.PI) * r
} else if (endAngle
< Math
.PI * 2) {
endPointX
= circleX
+ Math
.sin(endAngle
- Math
.PI * 3 / 2) * r
endPointY
= circleY
- Math
.cos(endAngle
- Math
.PI * 3 / 2) * r
} else {
endPointX
= circleX
+ Math
.cos(endAngle
- Math
.PI * 2) * r
endPointY
= circleY
+ Math
.sin(endAngle
- Math
.PI * 2) * r
}
return {
startPointX
,
startPointY
,
endPointX
,
endPointY
}
}