饼图是我们常见的一种可视化图形,常用于表示一个样本或总体中各组成部分的占比情况。环形图与饼图类似,区别就在于中间掏出来一个“大洞”,它们可能是下面这样
那么如何用canvas实现一个饼图或者环形图呢?我们先看看代码
ctx.fillStyle = '#6cf';
ctx.save();
ctx.beginPath();
ctx.arc(300, 300, 180, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
通过上面这一串代码,我们画出了一个饼图,它长这样
ctx.fillStyle = '#6cf';
ctx.save();
ctx.beginPath();
ctx.arc(300, 300, 180, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
再通过上面这串代码,我们实现了一个环形图,它长这样
上面代码看起来很简单,我们很快就画出来两个图,但聪明的胖虎脑袋一闪,眉头一紧,发现这事没有那么简单!
饼图我们就画一个圆,填色自然就填到圆里面,没什么可说的,可环形图我们画了两个圆,填色的时候为什么只填了两个圆之间的夹层呢?为什么不是填
到内层圆呢?
细心的小伙伴已经发现了端倪,我们在画环形图的第二个圆时调用canvas的API多传入了一个字段,问题就在这,下面我们来一探究竟。
首先我们先来看看上面调用的API
void ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
x ---- 圆弧中心(圆心)的 x 轴坐标
y ---- 圆弧中心(圆心)的 y 轴坐标
radius ---- 圆弧的半径
startAngle ---- 圆弧的起始点, x轴方向开始计算,单位以弧度表示
endAngle ---- 圆弧的终点, 单位以弧度表示
anticlockwise ---- 可选的Boolean值 ,如果为 true,逆时针绘制圆弧,反之,顺时针绘制。
接下来我们再补习补习一波数学知识。
- 向量
-
- 向量即具有大小和方向的量,可形象化的表示为带有箭头的线段
- 单位向量即长度为一个单位的向量
-
- 向量加法。
- 向量加法。
- 切线。一条刚好触碰到曲线上点的直线,准确说,当切线经过曲线上某点时,切线的方向与曲线上该点的方向是相同的
下面我们重点看看上面的API----arc的第六个参数。从上面的描述我们看到,如果设置为true,则逆时针画,反之顺时针。
针对上面这一特性,浏览器规定了一个定则,从某曲面图形内任一点做一条线,方向朝曲面图形外,必定与曲面有一相交点(可能会与多个曲面相交,则后面步骤每个相交点都一致),做该相交点的切线作为单位向量,方向与曲面图形的绘制方向相同。
假设设置顺时针为正向(逆时针为正向也一样)
将该线的所有相交点的单位向量加起来,如果向量相加后的大小(模)不等于0,则认为该点是位于曲面的填色范围内,相反向量的大小(模)等于0,则认为该点不位于曲面的填色范围内。大致流程可以看下面的🌰
上面的图按照之前的步骤操作后,我们发现点a位于填色范围内,点b不在范围内,点c位于填色范围内,那么也就是说a点和c点所在的区域都会填色,而b点则不会,绘制出来就是这个样子。
完结,撒花!