百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

鸿蒙开源第三方组件——MPAndroidChart_ohos 图表绘制组件

bigegpt 2024-08-10 12:15 8 浏览

前言

本组件是基于安卓平台的图表绘制组件MPAndroidChart(https://github.com/PhilJay/MPAndroidChart),实现了其核心功能的鸿蒙化迁移和重构。目前代码已经开源到(https://gitee.com/isrc_ohos/mpandroid-chart_ohos),欢迎各位下载使用并提出宝贵意见!

背景

安卓版本的MPAndroidChart在GitHub上有超过3.3万个Star和8.3k个Fork,应该说是目前使用最广,体验最佳的开源图表库。它具绘制折线图、饼图、雷达图等图表的能力,用户只需要自己写一个数据接口,即可实现各种精美数据曲线的绘制,在一定程度上满足了大部分业务的需求。

本组件是MPAndroidChart的鸿蒙化版本,名为MPAndroidChart_ohos,实现了其核心功能。

组件效果展示

目前MPAndroidChart_ohos具有折线图和直方图两种图表绘制能力。下面将分别展示其折线图和直方图的绘制效果。

1、折线图

图1展示了一个由随机数据生成的折线图。MPAndroidChart_ohos继承了原版MPAndroidChart的优秀特性,提供了多种多样的用户自定义接口,例如:

(1) X、Y轴自定义。使用者可以自定义X、Y轴的位置,例如在这个sample里就绘制了左Y轴和上X轴。

(2)辅助线自定义。使用者可以选择是否显示辅助线(或格点线),也可以自由设定辅助线的位置。

(3)图表美化。使用者可以设置图表曲线的各种属性(颜色、粗细等),还可以对曲线包裹区域进行填充。

2、直方图

图2是基于假设场景“2020年1月1日 ~ 15日的小卖部收益情况”绘制的图表。基于这个背景,使用MPAndroidChart_ohos制作了一张直方图。


Sample解析

图1和图2主要依靠调用Library中的能力绘制,在Sample中的实现主要由图3中红框所示的两个文件来完成。

如果用户想要绘制图表,只需要完成以下几个步骤即可:

(1)选择图表种类。

(2)设置属性。

(3)导入数据

1、选择图表种类

MPAndroidChart_ohos提供了折线图和直方图的绘制能力,使用者只需要根据自身需求选择需要使用的能力即可。

LineChart chart = new LineChart(context);  //折线图的初始化
BarChart chart = new BarChart(context);    // 直方图的初始化

2、设置属性

MPAndroidChart_ohos提供了图表样式自定义的能力,使用者可以通过调用Library暴露的接口来给图表添加、修改、删除各项属性。例如使用者想要自定义轴线,可以通过实例化XAxis 类的对象,然后通过对象的各种方法实现修改X轴的颜色,设置最大值、最小值等:

XAxis xAxis = chart.getXAxis();  // 实例化
xAxis.setAxisMaximum(20f);   //属性设置
xAxis.setAxisMinimum(0f);
xAxis.setAxisLineColor(Color.BLACK.getValue());

除了轴线设置以外还可以在图表中加入各种辅助线,例如想要在x = 2处添加一条辅助线,可以通过实例化LimitLine 类的对象,然后通过对象的各种方法实现修改辅助线的宽度、标签位置、文本大小等:

LimitLine llXAxis = new LimitLine(2f, "辅助线:x=2");  // 实例化
llXAxis.setLineWidth(4f);                       //属性设置
llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM);
llXAxis.setTextSize(10f);
llXAxis.setTypeface(Font.DEFAULT);


3、导入数据

在MPAndroidChart_ohos中,不同类型的图表有着不同的数据类,例如折线图的数据类为LineData,直方图的数据类为BarData,为什么不能仅仅通过一个简单int[]或者float[]作为数据类呢?这是因为在MPAndroidChart_ohos中数据类的作用不仅仅是承载数据,同时还需要承载一些图表相关的属性,例如曲线颜色、曲线粗细、数据点颜色、大小等,这样做的意图在后续Library分析时会讲到。

以折线图为例,导入数据的过程如下:

(1)创建LineDataSet类:

LineDataSet set1 = new LineDataSet(values, label);

其中values是使用者想要绘制的一类数据,一般是float[],label是这类数据的标签。

(2)将一类或者几类数据放置到一个ArrayList中

ArrayList<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(set1);

(3)将ArrayList做成LineData数据类,并传递给chart

LineData data = new LineData(dataSets);
chart.setData(data);


Library解析

1、工程结构对比

从图4中的两张图的对比可以看出,MPAndroidChart_ohos是按照MPAndroidChart工程的结构开发的,实现了其主要功能。相较于MPAndroidChart,虽然MPAndroidChart_ohos缺少exception、highlight、jobs这几个文件夹,但并不影响其主要功能的使用。

2、多设备适配

为了增加多设备适配性,MPAndroidChart内部以dp(density independent pixels)为单位来计算图表中各个部件的相对位置,在绘制图表时,统一将dp数据转化为pixel数据,在这个过程中就需要系统提供一些显示信息。在安卓中,这些信息由DisplayMetrics来提供,如下代码可以通过上下文获取到DisplayMetrics:

Resources res = context.getResources();
mMetrics = res.getDisplayMetrics();

接下来通过DisplayMetrics可以获取到屏幕的DPI,dp * DPI即为屏幕的pixel:

public static float convertDpToPixel(float dp) {
        return dp * mMetrics.density;
}


在鸿蒙系统中,显示信息通过DisplayAttribute类来获取,以下代码可以获取到DisplayAttribute:

Display display = DisplayManager.getInstance().getDefaultDisplay(this.getContext()).get();
DisplayAttribute displayAttribute = display. getAttributes()

可以看出与安卓还是有些许不同的。得到DisplayAttribute后即可得到屏幕DPI,需要注意的是代表DPI的接口与安卓不同:

public static float convertDpToPixel(float dp) {
        return dp * mMetrics.densityPixels;
}


3、轴线绘制

轴线是一张图的基准,在MPAndroidChart中,轴线甚至作为了图表种类的分类基准!看似MPAndroidChart提供了十余种图表绘制的能力,其实这十余种图表是依托于两种轴线制作的,这两种轴线分别是平面直角坐标系和极坐标系。

在直角坐标系下,MPAndroidChart实现了折线图、散点图、直方图、气泡图、蜡烛图等。

在极坐标系下,MPAndroidChart实现了饼图、雷达图。

在MPAndroidChart_ohos中,和轴线相关的类主要分布在components文件夹和renderer文件夹中:

其中AxisBase类主要定义了轴应具备的属性,例如颜色、粗细、位置、刻度、标签、最值等。XAxis和YAxis继承自AxisBase,并分别定义了X、Y轴所应具备的属性,例如:X轴的位置属性应是“Top”、“BOTTOM”、“TOP_INSIDE”、“BOTTOM_INSIDE”或“BOTH_SIDED”中的一种;而Y轴与X轴不同,其位置属性应为“LEFT”或“RIGHT”。

AxisRenderer类是绘制轴线的基类,其定义了绘制轴线所必备的属性和方法,例如用于绘制轴线、标签、辅助线、格点的几种画笔(Paint)和对应的方法接口。XAxisRenderer和YAxisRenderer继承自AxisRenderer,实现了其中用于绘制的接口,真正实现了轴线的绘制。其他的诸如XAxisRenderHorizontalBarChart类从名字上看也容易得知是在一些特殊图表上绘制轴线用的。

4、数据绘制

在Sample解析中提到对于不同类型的图表,需要不同的数据类去承载数据和属性。数据类的继承关系是MPAndroidChart中比较复杂的一部分内容,举一个例子来说,我们绘制折线图所需的LineData类,它继承自:

public class LineData extends BarLineScatterCandleBubbleData<ILineDataSet> {

类名有点长,不过没关系,继续向下寻找:

public abstract class BarLineScatterCandleBubbleData<T extends IBarLineScatterCandleBubbleDataSet<? extends Entry>> extends ChartData<T> {

ChartData类应该就是根了:

public abstract class ChartData<T extends IDataSet<? extends Entry>> {


看似三级继承关系并不算多,但是值得注意的是期间需要实现的接口和泛型参数是非常多的,这些接口和泛型往往还都能继续向下嵌套好多层,这着实给移植工作带来了一些困难。下面来看看这些数据类是做什么的。

ChartData类是数据类的基类,在其中首先定义了数据的上界和下界分别是浮点数所能代表的最大和最小值,同时该类提供了一些数据处理方法,例如如果发现任何数超过了上、下界,都将这些数强制赋值为上、下界,避免溢出带来的数据错误。同时这个类还提供了诸如查询数据点个数、查询数据X、Y值、查询标签、查询最大、最小值等数据查询方法。

BarLineScatterCandleBubbleData和LineData分别是对ChartData的一次和二次封装,本身并没有添加任何方法,只是通过实现接口与各种泛型参数对存入其中的数据格式加以限制。

那么数据点和曲线是如何绘制到图表中的?DataRenderer是数据绘制的基类,其中写出了绘制数据、曲线、标签等的抽象方法。继续以折线图为例,这些抽象方法将在DataRendereràBarLineScatterCandleBubbleRendereràLineScatterCandleRadarRendereràLineRadarRendereràLineChartRenderer这个继承路径中被逐步实现,最终LineChartRenderer实现了绘制折线图的全部能力。

项目贡献人

吴圣垚 郑森文 朱伟 陈美汝 张馨心

相关推荐

C#.NET Autofac 详解(c# autoit)

简介Autofac是一个成熟的、功能丰富的.NET依赖注入(DI)容器。相比于内置容器,它额外提供:模块化注册、装饰器(Decorator)、拦截器(Interceptor)、强o的属性/方法注...

webapi 全流程(webapi怎么部署)

C#中的WebAPIMinimalApi没有控制器,普通api有控制器,MinimalApi是直达型,精简了很多中间代码,广泛适用于微服务架构MinimalApi一切都在组控制台应用程序类【Progr...

.NET外挂系列:3. 了解 harmony 中灵活的纯手工注入方式

一:背景1.讲故事上一篇我们讲到了注解特性,harmony在内部提供了20个HarmonyPatch重载方法尽可能的让大家满足业务开发,那时候我也说了,特性虽然简单粗暴,但只能解决95%...

C# 使用SemanticKernel调用本地大模型deepseek

一、先使用ollama部署好deepseek大模型。具体部署请看前面的头条使用ollama进行本地化部署deepseek大模型二、创建一个空的控制台dotnetnewconsole//添加依赖...

C#.NET 中间件详解(.net core中间件use和run)

简介中间件(Middleware)是ASP.NETCore的核心组件,用于处理HTTP请求和响应的管道机制。它是基于管道模型的轻量级、模块化设计,允许开发者在请求处理过程中插入自定义逻辑。...

IoC 自动注入:让依赖注册不再重复劳动

在ASP.NETCore中,IoC(控制反转)功能通过依赖注入(DI)实现。ASP.NETCore有一个内置的依赖注入容器,可以自动完成依赖注入。我们可以结合反射、特性或程序集扫描来实现自动...

C#.NET 依赖注入详解(c#依赖注入的三种方式)

简介在C#.NET中,依赖注入(DependencyInjection,简称DI)是一种设计模式,用于实现控制反转(InversionofControl,IoC),以降低代码耦合、提高可...

C#从零开始实现一个特性的自动注入功能

在现代软件开发中,依赖注入(DependencyInjection,DI)是实现松耦合、模块化和可测试代码的一个重要实践。C#提供了优秀的DI容器,如ASP.NETCore中自带的Micr...

C#.NET 仓储模式详解(c#仓库货物管理系统)

简介仓储模式(RepositoryPattern)是一种数据访问抽象模式,它在领域模型和数据访问层之间创建了一个隔离层,使得领域模型无需直接与数据访问逻辑交互。仓储模式的核心思想是将数据访问逻辑封装...

C#.NET 泛型详解(c# 泛型 滥用)

简介泛型(Generics)是指在类型或方法定义时使用类型参数,以实现类型安全、可重用和高性能的数据结构与算法为什么需要泛型类型安全防止“装箱/拆箱”带来的性能损耗,并在编译时检测类型错误。可重用同一...

数据分析-相关性分析(相关性 分析)

相关性分析是一种统计方法,用于衡量两个或多个变量之间的关系强度和方向。它通过计算相关系数来量化变量间的线性关系,从而帮助理解变量之间的相互影响。相关性分析常用于数据探索和假设检验,是数据分析和统计建模...

geom_smooth()函数-R语言ggplot2快速入门18

在每节,先运行以下这几行程序。library(ggplot2)library(ggpubr)library(ggtext)#用于个性化图表library(dplyr)#用于数据处理p...

规范申报易错要素解析(规范申报易错要素解析)

为什么要规范申报?规范申报是以满足海关监管、征税、统计等工作为目的,纳税义务人及其代理人依法向海关如实申报的行为,也是海关审接单环节依法监管的重要工作。企业申报的内容须符合《中华人民共和国海关进出口货...

「Eurora」海关编码归类 全球海关编码查询 关务服务

  海关编码是什么?  海关编码即HS编码,为编码协调制度的简称。  其全称为《商品名称及编码协调制度的国际公约》(InternationalConventionforHarmonizedCo...

9月1日起,河南省税务部门对豆制品加工业试行新政7类豆制品均适用投入产出法

全媒体记者杨晓川报道9月2日,记者从税务部门获悉,为减轻纳税人税收负担,完善农产品增值税进项税额抵扣机制,根据相关规定,结合我省实际情况,经广泛调查研究和征求意见,从9月1日起,我省税务部门对豆制品...