图表绘制小结

最近工作中,完成了绘制图表功能,在这个过程中踩了一些坑,在这里分享给大家。

需求分析

接到需求后,开始进行需求分析,其他模块上已有完善的图表绘制功能,相关交互也有,因此,可行性是没问题的。在功能分析时,该功能内嵌3个子图表,每个图表有不同的绘制样式和叠加需求,可通过参数来控制差异,绘制流程是可复用的。

接下来分析现有绘制功能模块,发现现有实现考虑了众多绘制场景和特殊情况,针对本需求,有一些场景和情况是不会发生的,因此就有两种方案:

  • 方案一: 在通用绘制模块中,添加控制参数和显示变量,来满足当前需求
  • 方案二: 基于通用绘制模块,复制一份副本,在副本中,删除于当前需求无关的部分,并针对当前需求进行定制化

鉴于原先的绘制模块已经足够复杂,再增加控制变量,恐怕会对其他模块造成影响,因此,采用方案二。

定好方案后,然后结合需求和已有模块进行功能梳理,参考具体方案设计。

具体方案设计

通过梳理已有绘制模块的实现逻辑,主要要考虑以下几点:

  1. 数据预处理
  2. 图表坐标
  3. 图例
  4. 展示样式
  5. 副图
  6. 交互

下面分别来介绍。

数据预处理

数据预处理是针对后台返回的数据,进行预先处理,方便后续绘制。通过分析图表绘制逻辑,可将显示数据抽象为如下结构:


struct TChartData
{
public:
	// 添加数据 
	void Add(unsigned int nDate, double data)

    // 更新数据附加信息
	void UpdateDataExInfo();

    // 获得数据集中的最大、最小值
    void GetMaxMin(double& dMax, double &dMin);
	
	// 获得展示单位
	string GetUnit();

private:
	vector<unsigned int> m_vDate;	// 日期
	vector<double>		 m_vData;	// 数据值
	
	double 				m_dMaxValue;  // 最大数
	double 				m_dMinValue;  // 最小数
	double 				m_dUnit;      // 展示单位
}

在上述结构中,日期采用 20211112 格式或者 134523 格式,分布表示日期或时间;数据采用 double 保存,整个数据集合按时间升序保存。

因为绘制需要,TChartData 提供 GetMaxMin 接口,同时对最大值进行向上取整、最小值进行向下取整。

为方便大数值展示,提供 m_dUnit 成员,方便图标坐标计算。

UpdateDataExInfo函数实例如下:


void UpdateDataExInfo()
{
	// .....
	double dValue = max(abs(dMax), abs(dMin));
	if (dValue > (10000.0 * 10000.0))
	{	
		m_dUnit = (10000.0 * 10000.0);	// 亿元
	}
	else if (dValue > (10000.0))
	{	
		m_dUnit = (10000.0);			// 万元
	}
	else
	{	
		m_dUnit = (1.0);			    // 元
	}
	
}

当有主、副图共同参与绘制时,还需要对主副图的数据进行对齐处理。此处需要产品确认绘制方案,主要考虑点:

  1. 对于某个序列有,另外没有时,如何处理?是留空、还是绘制特殊值?还是跳过不绘制?

图表坐标

通过前期数据预处理,绘制坐标就简单了,重点考虑以下几点:

  • 坐标说明
    • 垂直坐标的业务含义以及单位
    • 水平坐标的均匀显示
    • 坐标颜色显示
  • 坐标背景的水平、垂直分割线
  • 0轴坐标位置

这里,着重说明下0轴位置,因为它是后续绘制数据的基准。考虑到实际的数据分布,需要考虑如下三种情况:

  • 数据全正:0轴位于图表最下方,0轴对应的数值为最小值
  • 数据全负:0轴位于图表最上方。0轴对应的数值为最大值
  • 数据有正有负:0轴位于图表中间,其距离图表顶部的距离计算公式为 总绘制高度*数据最大值/(数据最大值-数据最小值) ,0轴对应的数值为0.

图例

图例说明图表上不同颜色曲线的业务含义。为了便于区分,在柱状图的0轴上下,使用不同颜色绘制。主副图使用不同颜色绘制。

图例要与坐标的业务说明保持一致,具体位置可上可下,根据需求来定。

展示样式

常用的展示样式有:折线图、柱状图、K线图。一个图表模块,需要支持按某种样式来绘制,并且主图和副图可单独设置。

样式绘制注意:

  • 折线图:为防止精度损失,要以浮点数来计算曲线点位置。点与点之间的距离根据总数量量和总绘制宽度来定,保证占满整个绘制区域。每单位数值对应的高度要提取算好。

  • 柱状图:为优化显示,在显示区域内居中绘制,柱子宽度固定。考虑靠近0值的柱子方向,大于0和小于0使用不同颜色绘制,以示区分。

副图

绘制副图,除了和主图的坐标位置不一样外,其他均一样。

交互提示

图表交互提示主要以下几种,在设计时,需支持外部设置.

  1. 悬浮框提示:在鼠标当前位置展示提示框,在框内显示时间以及业务数据
  2. 坐标高亮块:在鼠标当前位置对应的X\Y轴上,以高亮显示当前位置的时间以及业务数据

小结

本文总结在绘制图表时的注意事项,包括数据预处理、图表坐标、图例、展示样式、副图以及交互,并重点介绍数据预处理的设计思路。

另外,在基于已有实现开发新需求时,不要被别人写的代码误导,也不要盲目在通用功能模块中添加支持。要权衡需求影响以及现有模块的复杂度,尽量减少新增功能对现有业务的影响。

在重写过程中,自己要有思考,不能盲目照搬原有实现,那么是无助于成长。

posted @ 2022-03-30 11:00  浩天之家  阅读(56)  评论(0编辑  收藏  举报