声明:文中的MPChart代指MPAndroidChart.

本系列之前的文章介绍的MPChart中BarChart相关的一些绘制,接下来我们看看LineChart相关的绘制。这里以实际的运动相关的图表数据做业务支撑来讲解。MPChart图表支持多指触控方法,这里所有的图表自定义都关掉了这个属性,这样就减少Transformer,以及绘制过程中的更多的变动,相当于一个静态的图。通常图表在放大的过程中,坐标轴也会随之展现更小的刻度,复杂度就变高了,具体的显示的刻度就可能出现小数之类的等情况。

这里我们关掉触摸放大后,相当于一个静态的图。这时候,产品以及设计可能需要我们的X轴坐标、Y轴坐标等刻度尽可能地为整数,这样看起来比较美观。静态的情况下,因为没法移动,即便可以移动,首次展现也希望图表的数据能够比较居中,这就涉及到YAxis的自定义如何影响控制 Chart的相关展示逻辑的内容,本章节首先从这入手,讲解运动数据图表的绘制。

  • TimeAxis

这里自定义X轴TimeAxis,实际意义是一次运动耗费的时间,继承自XAxis。假如一次运动1个小时06分钟,设计希望展示4个刻度(0, 20 , 40, 60 分钟), 这时需要我们自己去控制,假如不加控制的话,Default情况下没法准确的实现设计的需求。

XAxis、YAxis有两个属性,Maximum, Minmum. 这样设定每个interval 就可以计算出要显示的刻度列表, labelList, 加入到XAxis中的 mEntries, 最后在XAxisRender会拿到mEntries 最终绘制 X坐标。

这里不在设计一个算法类计算每个时间段的刻度显示了,运动的时间范围有限,直接枚举, 在 TimeXAxis里的getlabelCount() 实现。

  if (max > 6000 * TimeDateUtil.TIME_MIN_INT){interval = 2000 * TimeDateUtil.TIME_MIN_INT;} else if (max > 4800 * TimeDateUtil.TIME_MIN_INT) {// 80个小时interval = 1920 * TimeDateUtil.TIME_MIN_INT;} else if (max > 2400 * TimeDateUtil.TIME_MIN_INT) {// 40个小时interval = 960 * TimeDateUtil.TIME_MIN_INT;} else if (max > 1200 * TimeDateUtil.TIME_MIN_INT) {interval = 480 * TimeDateUtil.TIME_MIN_INT;}。。。。。else if (max > 20 * TimeDateUtil.TIME_MIN_INT) {interval = 5 * TimeDateUtil.TIME_MIN_INT;} else if (max > 15 * TimeDateUtil.TIME_MIN_INT) {interval = 4 * TimeDateUtil.TIME_MIN_INT;//4分钟刻度} else if (max > 5 * TimeDateUtil.TIME_MIN_INT) {//interval = 2 * TimeDateUtil.TIME_MIN_INT;//2分钟刻度。} else {interval = TimeDateUtil.TIME_MIN_INT;}float currentEntry = min;List<Float> entryList = new ArrayList<>();do {entryList.add(currentEntry);currentEntry += interval;} while (currentEntry <= max);labelCount = entryList.size();mEntryCount = labelCount;if (mEntries.length < labelCount) {mEntries = new float[labelCount];}for (int i = 0; i < labelCount; i++) {mEntries[i] = entryList.get(i);}

准备好XAxis 中的Entry数据后,依旧是交给Buffer,经过Transformer转化,最终绘制出来, 自定义TimeAxisRender, 然后 renderAxisLabels() 方法里drawLabel(), 绘制XAxis的坐标轴线:

图1.0 XAxis 坐标线的绘制

  • SportYAxis

Y轴的绘制相比XAxis要复杂一些,自定义的SportYAxis继承自YAxis, TimeXAxis 只有时间数据对应。SportYAxis根据具体的数据业务可以表示 心率, 高度海拔, 速度, 配速,频率等数据。这些数据中, 心率、步频等取值范围可以比如(0, 250)类似这样的可以直接定下来Y轴的Max, Min 值以及对应的刻度,高度海拔有负数的,速度的Max根据 所给数据来定, 配速比较特殊,需要将Y轴 revert。

为了将图表能够居中,通常YAxis 上的Maximum 会比 数据中的极大值要偏大,保证图表不会呈现的太慢,影响美观。根据不同的Sport数据,将Y轴分为以下几种:

// TYPE_FIX_MIN_ZERO = 0; Y轴从固定的0开始 到 max;步频、起跳高度
// TYPE_FIX_MIN_POSITIVE = 1; 从 entryList的 真实的 min(min不能小于0)开始,到max; 心率、速度、划频、Swolf
// TYPE_FIX_COMMON = 2; 从entryList的最小值min开始到max的最大值,无论最大、最小是否为Positive, 例如海拔;
//TYPE_FIX_RESTRICT_MAX = 3; 限制最大值,比如配速。Y轴 Invert,所以最小值min为大于等于 0 的Positive value; 配速
public static final int TYPE_FIX_MIN_ZERO = 0;
public static final int TYPE_FIX_MIN_POSITIVE = 1;
public static final int TYPE_FIX_COMMON = 2;
public static final int TYPE_FIX_RESTRICT_MAX = 3;

每种类型下计算Y轴的Maximum、Minmum; 然后计算刻度的间距 itemValue, 得到 坐标Label 的List。

以上的几种坐标的实现具体在 SportYAxis 中实现。

将Y轴数据限定下来之后,图表的展现因为Y轴的Maximum、Minmum 限定在比较居中的位置。

对于配速,当运动停下来时,单位距离的耗时可能无限大,假如我们考虑把这个极值画下来的话,Y轴可能跨度很大导致图表没法看,所以需要限定极大值,截断图形:

//限制最大值
private float getYAxisMax2(List<SportRecordEntry> values, float yAxisMin) {int size = values.size();float yAxisMax = Integer.MIN_VALUE;float yAxisMinTemp = Integer.MAX_VALUE;float sum = 0;for (int i = 0; i < size; i++) {SportRecordEntry entry = values.get(i);yAxisMax = Math.max(entry.getY(), yAxisMax);yAxisMinTemp = Math.min(entry.getY(), yAxisMinTemp);sum += entry.getY();}float averageY = sum / (size * 1.0f);float distanceMin = averageY - yAxisMinTemp;float distanceMax = yAxisMax - averageY;int num = (int) (distanceMax / distanceMin);if (num > 5) {// 配速中 有 配速值很慢的点,坐标时不考虑它们了。yAxisMax = averageY + 2 * distanceMin; // 限制Y 轴坐标。}float distance = yAxisMax - yAxisMin;if (yAxisMax > 0 && distance <= 2) {return yAxisMax + 2;}return yAxisMax + distance * mLineChartAttr.maxYAxisRatio;
}
  • CustomLineChart

处理完XAxis、YAxis的数据及绘制后,处理LineChart的主体,这里包含了折线图、曲线图等体现数据展现的,还有drawFill, 底部的填充;drawMaxMinPop() 极值点的绘制等。着重讲解折线图的绘制,对于LineChart,Entry比较简单,存有对应的X, Y值,

图1.1CustomLineChart 绘制逻辑

考虑先后两个点,PreEntry, CurrentEntry 然后 绘制每段折线,最终连成图表。

针对 配速图表Y轴需要倒过来的,

private float getYAsInverted(Entry entry) {final float phaseY = mAnimator.getPhaseY();float yValueRange = mYAxis.getAxisMaximum() - mYAxis.getAxisMinimum();if (mYAxis.isInverted()) {if (entry.getY() <= mYAxis.getAxisMinimum()) {return entry.getY() * phaseY;} else {return (yValueRange - entry.getY()) * phaseY;}} else {return entry.getY() * phaseY;}
}

以下就是配速图表,极大值的限定线取的太大,导致整个图形太偏上了,可以做响应的修改。

图1.2配速图表线形图

绘制底部的Fill, 将所有的点连线,再连接到底部的X点坐标,最后形成闭环的Path,

图1.3 drawFill

以上大致就是线性图表的绘制逻辑,考虑X轴、Y轴的Label的设定,绘制,Y轴的极值设定来控制图表图形呈现的位置;配速表的这种Y轴图形的invert, 底部的drawFill().

自此大体的自定义绘制讲解完了。后续会做些补充,步频散点图,极值的绘制,RTL相关等。

作者:yxc
链接:https://juejin.cn/post/7138238565850775559
来源:稀土掘金

MPAndroidChart 运动数据图表自定义相关推荐

  1. mpAndroidchart 坐标和图表距离_数据对比图表,如何让你的总结报告更具说服力!...

    数据对比大揭秘,业绩PK看这里. "数据解锁表达,用好PPT图表,让我们的演示更有说服力." 数据,作为PPT报告中最重要的呈现要素,借助图表的展示形式,能够将冰冷的文本数据更直观 ...

  2. 数据图表与分析图_史上最全最实用的数据可视化分析图表制作工具汇总

    俗话说的好:工欲善其事,必先利其器!一款好的工具可以让你事半功倍,尤其是在大数据时代,更需要强有力的工具通过使数据有意义的方式实现数据可视化,还有数据的可交互性;我们还需要跨学科的团队,而不是单个数据 ...

  3. 科研ABC - 数据图表的绘制

    数据图表的绘制 1 常用软件 1.1 Origin 1.2 Matlab 1.2.1 一系列的高层绘图函数 1.2.2 低层绘图功能 1.3 PowerPoint 1.4 Photoshop 1.5 ...

  4. 计算机数据表格展示,利用工具,一分钟完成数据可视化,快速输出美观的数据图表...

    天天跟表格打交道的办公室的表哥表妹,为了能让老板看的更一目了然,可以说是费时费力. 今天小姐姐给大家分享一下如何利用工具,一分钟完成数据可视化,快速输出美观的数据图表. [新手们必须收藏转发呀] 为什 ...

  5. 关于开发微信公众号获取手机用户运动数据的功能实现思路

    一.前沿研究 微信公众号开发文档,浏览后没有任何关于获取微信运动数据的接口 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp144 ...

  6. Axure可视化动态数据图表6合1元件库

    Axure可视化动态数据图表6合1元件库 立即获取源文件 Axure可视化动态数据图表元件库包含了Echats图表组件 ,Gallery图表组件.AntV G2图表组件.AntV G6图表组件.Ant ...

  7. echarts图表自定义图例

    在echarts中自定义图例样式 就跟表格一样清晰的展示数据 <!-- 图表容器 --> <div id="myChart1" ref="myChart ...

  8. f-scan足底压力分析二:对象、单元统计、绘制压力数据图表、ASCII DATA

    目录 对象 在movie或实时窗口中添加窗格 在movie或实时窗口中添加取样区box 栅格调整 grid adjustement 改变对象显示的数据 选择新位置放置取值区标签 单元格统计 绘制单元格 ...

  9. ASP.NET实现数据图表

    作者:马金虎  来自:yesky 在ASP中插入图表,常用的方法是使用MSChart控件.那么在ASP.NET是否也是这样呢?答案是不可以的. 我们知道ASP.NET是一种编译语言,当客户端第一次调用 ...

最新文章

  1. 解决Android手机 屏幕横竖屏切换
  2. Hadoop MapReduce实例:按照手机号归属地分区统计手机上网流量(Reduce Task进程数设置)
  3. 分手后我还能和你做朋友么(转)
  4. 第25月第2天 Django-By-Example项目记录01
  5. Simulink之理想开关
  6. 常用HDFS java API
  7. 苏州大学计算机考研大纲2021,2021苏州大学考研参考书目
  8. 2017、2018年JS面试题记录分享
  9. ORB-SLAM2 ---- Tracking::Relocalization函数
  10. org.apache.tools.ant.Task在哪个jar包
  11. 面壁人VS智子 --- 搜索排序的作弊和反作弊
  12. wiring的运行(使用open source产品组装你的web应用架构)
  13. 学会了这个配音方法,我的视频居然成了热门爆款
  14. 怎么给苹果手机设备画面投屏到电脑上面?
  15. 2022java学习路线总结—纯干货分享
  16. 迅为4412开发板(全能版)V_4.0 ubuntu 在Android4.4.4的内核下移植wifi
  17. wav文件的采样位数从16位转换到8位的C语言实现
  18. Linux 根目录及相应子目录解析
  19. JVM 参数及含义(适用于 JDK7及之前)
  20. 浅谈NFT抵押借贷的三种模式:点对点、资金池和中心化模式

热门文章

  1. 【linux进阶9】linux中的iptables火墙优化策略
  2. 享受知识饕餮盛宴,尽在2015年课程体系
  3. 怎么将歌曲的一部分截取设置为手机铃声
  4. 详解shell脚本中的变量
  5. 硅谷创业群英和个人及计算机的崛起历史
  6. 半导体器件与集成电路实验报告 实验二 PN结电容的测量
  7. 区位码、国标码与机内码的转换关系
  8. DA14583 OTA 固件升级
  9. plc和单片机及c语言区别,PLC和单片机有什么区别?如何分清PLC和单片机
  10. C4D R26 渲染学习笔记 建模篇(0):建模常识