最近在做一个跟数据核算相关的web项目,其间会展现一些饼图,折线图以及柱状图这样的图表组件,能够根据一套数据别离运用不同的图表组件来展现,还是蛮有意思的,但有意思归有意思,职业病联系,我还是想自己上手来测验一下,这篇文章我就先用Compose来做一个饼图组件吧

源码地址

这个组件需求支撑

  • 单个饼图或许多个饼图来展现不同维度的数据
  • 环形与实心饼图的款式切换
  • 展现饼图时需求有动画作用
  • 环形饼图可设置环的粗细巨细
  • 饼图的区间色彩可由数据动态操控
  • 饼图周围需支撑展现对应数据的描绘

这个组件怎么做

预备数据

首要第一步咱们将需求展现饼图用到的数据先罗列出来,一般性饼图的数据是一个数组,数组里边每个元素都会至少包括三个特点,一个是饼图区间的称号,一个是饼图区间的详细数值,还有一个是饼图区间色块的色值,咱们将这些特点封装在一个数据类里边

一步一步来做一个Compose版的饼图组件

PieData就表示单个区间块,一个饼图是由若干个PieData组成,所以这儿再创立一个PieData的数组,作为展现饼图需求的数据源

一步一步来做一个Compose版的饼图组件

制造饼图

现在创立个函数Pie,咱们制造单个饼图就在Pie里边进行,让dataList作为Pie的一个参数,别的增加个modifier参数,可由调用方操控饼图的巨细

一步一步来做一个Compose版的饼图组件

饼图是由若干个扇形拼接组成的,所以这儿需求制造datalist.size()个拥有同一个topLeft的扇形,咱们先核算出扇形的半径,即画布中心点xy轴的最小值的一半

一步一步来做一个Compose版的饼图组件

这个radius决定了饼图制造的范围巨细,而单个扇形的巨细则是由sweepAngle来操控,可是sweepAngle对应的是视点,咱们只知道每个扇形对应的详细数值巨细,这儿就需求一个公式来将这个数值转换成视点,公式如下

一步一步来做一个Compose版的饼图组件

在这个公式里边咱们仅有需求去获取的便是一切数值的总和,那么针对一个List里边某个特点求和咱们能够运用mapreduce操作符来完成,代码如下

一步一步来做一个Compose版的饼图组件

这样就获得了一切数值的总和total,接着运用上述公式,咱们就能将一切扇形的sweepAngle都核算出来,而且都放在一个List当中,代码如下

一步一步来做一个Compose版的饼图组件

rateList里边就放着一切扇形的sweepAngle,咱们能够经过遍历rateList来将一切扇形制造出来,至于startAngle,咱们能够这样想,第一个扇形的startAngle一定是在-90度,第二个那便是在第一个扇形的startAngle上加上第一个扇形的sweepAngle,得到的成果便是第二个扇形的startAngle,以此类推下去,代码如下

一步一步来做一个Compose版的饼图组件

这儿值得注意的是,咱们数据里边的color是一个十六进制的字符串,由于正式场景下这些数据都来自于后端,后端接口不可能直接返回咱们能够运用的Color类,所以这儿运用了hexToInt函数将字符串转成十六进制的Int类型才能够色值来运用,终究咱们的饼图就制造出来了

一步一步来做一个Compose版的饼图组件

这儿制造出来的是实心的饼图,但有些时分要求饼图是一个环形的,那么这儿就需求将style特点设置为Stroke,而且传一个环的粗细巨细,别的还要将useCenter特点设置为false,让扇形两端不要与圆心相连,环形的饼图代码如下

一步一步来做一个Compose版的饼图组件

这样就得到了一个环形的饼图

一步一步来做一个Compose版的饼图组件

现在咱们要让饼图的实心款式与环形款式可装备,要让Pie函数能够经过一个参数来决定该饼图究竟该运用哪种款式,那么这儿咱们新创立一个枚举类,里边界说两个值别离代表环形款式与实心款式

一步一步来做一个Compose版的饼图组件

然后给Pie函数新增一个ChartType的参数,默认值为Full实心款式,别的圆环的粗细也用一个参数来表示,让它也能够装备,修改后的Pie函数代码如下所示

一步一步来做一个Compose版的饼图组件

动画

制造部分的代码完成的差不多了,可是现在只能很僵硬的将饼图显示出来,这个显着是不够的,任何一个图表组件在展现的时分都会有它自己特有的动画,比如折线图是从第一个点连线到最后一个点,柱状图是每一根柱子逐步变长,饼图则是从0度开端逐步展开至360度,那么怎么来做呢,要是只要一个扇形要完成一个从0度展开至360的动画,很简单,运用animateFloatAsState函数,target值传360度就能够了,可是这儿可不只是只要一个扇形,是多个扇形,那么就需求创立多个animateFloatAsStatetarget值便是rateList里边的值,经过遍历来创立多个动画变量,代码如下

一步一步来做一个Compose版的饼图组件

这儿将创立出来的动画变量放进了diffAngleList的数组中,而且运用LaunchedEffectFlow制造出了一个定时器,模拟一个接纳到数据之后动画展现饼图的进程,然后还要将制造饼图部分的sweepAngle的值替换成diffAngleList里边的值

一步一步来做一个Compose版的饼图组件

来看下展现出来的作用怎么

一步一步来做一个Compose版的饼图组件

能够发现扇形尽管都有了动画作用,可是这些动画并没有连起来,并没有展现出第一个动画完毕今后才进行第二个动画的作用,那么怎么改呢?咱们这儿能够运用延迟动画来完成,虽说这些扇形的动画都是一起开端的,但咱们能够让除了第一个扇形之外的其他扇形在开端动画前有个延迟开端的时刻,这个时刻的巨细便是前面扇形的动画时刻的总和,更改后的代码如下

一步一步来做一个Compose版的饼图组件

现在再看下作用就不相同了

一步一步来做一个Compose版的饼图组件

有点那个感觉了是不,趁便再试下环形款式的作用

饼图的动画也完成了,接下来便是将饼图的一些数据描绘展现出来

展现数据描绘

饼图的数据描绘根本由色块色彩,称号和数值组成,方位常见的有散布在饼图圆周方向,以及在饼图上下左右某一侧线性排列,所以咱们这个组件应该要具有一个可装备描绘方位的功用,那么相同给描绘方位也增加几个枚举值

一步一步来做一个Compose版的饼图组件

相同也给Pie函数增加一个DescriptionDirection参数,而且默认值设置为左侧

一步一步来做一个Compose版的饼图组件

DescriptionDirection.LEFT

先来画左侧的案牍,运用drawText函数来完成,drawRect函数来制造色块

一步一步来做一个Compose版的饼图组件

这儿首要创立了一个变量mGap,为什么要创立这个变量呢,这是用来核算drawText时分topLeft的位移,由于当饼图是实心的时分,它的半径永远都是radius,可是当变成环形的时分,饼图的半径就会变成radius+mGap/2,也便是实心饼图不需求考虑gap巨细,别的还设置了文本巨细textSize,这个巨细一起也作为了色块的巨细,方位上,每个文本的x坐标都是相同的,都是画布中心x坐标减去radius+mGap/2+200f,多增加200f主要是为了不让文本与饼图有堆叠部分,色块的x坐标在文本的基础上多增加了两倍的文本巨细,为的也是不让色块与文本堆叠,而y坐标的逻辑根本都是初始方位在centerY-radius上,然后逐一递增(radius * 2)/dataList.size,色块多增加了个textSize的距离,意图也是尽量与文本对齐一些,左侧描绘的代码根本都是这样,咱们看下作用

一步一步来做一个Compose版的饼图组件

上下和右侧的饼图描绘根本同左侧相同,只是在topLeft的核算上有点收支,就不重复讲了,直接上代码跟作用图

DescriptionDirection.RIGHT

一步一步来做一个Compose版的饼图组件
一步一步来做一个Compose版的饼图组件

DescriptionDirection.TOP

一步一步来做一个Compose版的饼图组件
一步一步来做一个Compose版的饼图组件

DescriptionDirection.BOTTOM

一步一步来做一个Compose版的饼图组件
一步一步来做一个Compose版的饼图组件

DescriptionDirection.CIRCLE

最后一个让描绘绕着圆周方向,那么每一个描绘当然是要在所对应的扇形视点的中心方位,比如每一个描绘的方位视点是90f+rateList[it]/2+prefixAngle,有了视点,核算每一个描绘的topLeft坐标就需求依托下面两个函数

一步一步来做一个Compose版的饼图组件

代入到drawText函数中,咱们制造文本的代码如下

一步一步来做一个Compose版的饼图组件

制造色块的代码在文本的基础上略微偏移点方位,代码如下

一步一步来做一个Compose版的饼图组件

现在再运行下代码,咱们的描绘方位便是在圆周方向了

一步一步来做一个Compose版的饼图组件

多个维度展现

咱们这个组件做的根本差不多了,现在还差最后一步,也便是咱们前面讲的都是以一组数据,一个维度来展现饼图,但实际场景下经常会出现多维度的场景,所以咱们也需求对这种场景提供支撑,这儿在创立个函数叫PieChart,这个函数接纳一组多维度数据的PieData

一步一步来做一个Compose版的饼图组件

这个函数内部,咱们运用一个LazyVerticalGrid组件来展现咱们的饼图,这个组件咱们界说为两列,交叉轴上展现两个饼图,代码如下

一步一步来做一个Compose版的饼图组件

现在这儿的饼图都是一种类型,也便是实心的,描绘依照圆周方向排列,咱们再界说几组数据传给函数PieChart

一步一步来做一个Compose版的饼图组件

得到的作用如下

一步一步来做一个Compose版的饼图组件

相同的,咱们把款式都切换成环形的再看看作用

一步一步来做一个Compose版的饼图组件
一步一步来做一个Compose版的饼图组件

总结

这个Compose版别的饼图组件算是竣工了,一些视觉方面的东西后期还会再优化下,功用上大致已经完成了饼图组件的根本功用了,可是不能说完成了一切功用,比如鼠标放在某个扇形区域时这个区域会变大,后续会针对这些细节逐一再完善这个组件。