在图表中,横轴通常表示分类,纵轴表示数值。
纵轴的数值标签表示,是需要算法支持的,参见【图表轴刻度的思路,算法: 转载X】,略过。
这里说说横轴(X轴)的标签。
用K线图做例子,在一个图中表示的蜡烛线非常多,每根线对应一个时间,这些时间就是X轴上要表示的标签。
如果每根线的时间都在X轴表示出来,由于数量太多,就会相互重叠,根本分不清彼此,上面的文字让看不出来。
因此就要减少其数量。如何减少数量?
百度的echarts(http://echarts.baidu.com/)中有K线图,分析其源码(\src\component\categoryAxis.js 中【_getInterval】函数),了解到起设计思路。
/**
* 计算标签显示挑选间隔
*/
_getInterval : function () {
var interval = this.option.axisLabel.interval;
if (interval == 'auto') {
// 麻烦的自适应计算
var fontSize = this.option.axisLabel.textStyle.fontSize;
var data = this.option.data;
var dataLength = this.option.data.length;
if (this.isHorizontal()) {
// 横向
if (dataLength > 3) {
var gap = this.getGap();
var isEnough = false;
var labelSpace;
var labelSize;
var step = Math.floor(0.5 / gap);
step = step < 1 ? 1 : step;
interval = Math.floor(15 / gap);
while (!isEnough && interval < dataLength) {
interval += step;
isEnough = true;
labelSpace = Math.floor(gap * interval); // 标签左右至少间隔为3px
for (var i = Math.floor((dataLength - 1)/ interval) * interval;
i >= 0; i -= interval
) {
if (this.option.axisLabel.rotate !== 0) {
// 有旋转
labelSize = fontSize;
}
else if (data[i].textStyle) {
labelSize = zrArea.getTextWidth(
this._getReformedLabel(i),
this.getFont(
zrUtil.merge(
data[i].textStyle,
this.option.axisLabel.textStyle
)
)
);
}
else {
/*
labelSize = zrArea.getTextWidth(
this._getReformedLabel(i),
font
);
*/
// 不定义data级特殊文本样式,用fontSize优化getTextWidth
var label = this._getReformedLabel(i) + '';
var wLen = (label.match(/\w/g) || '').length;
var oLen = label.length - wLen;
labelSize = wLen * fontSize * 2 / 3 + oLen * fontSize;
}
if (labelSpace < labelSize) {
// 放不下,中断循环让interval++
isEnough = false;
break;
}
}
}
}
else {
// 少于3个则全部显示
interval = 1;
}
其设计思路主线是(如果分析错误,见谅!)
1. 遍历所有蜡烛线,找到其对应的标签文字最长的,计算其占用的空间长度(像素)
2. 设定标签之间的间隔(interval),计算其空间长度(像素)
3. 比较上面长度关系
4. 如果interval长度不足以容下最长文字,则增加interval,继续循环比较。直到找到合适的interval。
==================================
var step = Math.floor(0.5 / gap);
interval = Math.floor(15 / gap);
==================================
代码中的数字【0.5】【15】似乎是尝试出来的经验值,不具有普遍性。
代码逻辑看起来比较复杂,不容易懂。
echarts的上面的代码抛砖引玉,提供了思路。
应该有足够简单的设计能够替代。