问题提出:不知大家,在使用echarts插件时候,有木有发现echarts的配置项里面没有刻度轴二级刻度的配置项。这个小细节,对于普通的图表使用者无关痛痒,因为有一级刻度基本上就能达到项目需求。但是在数据的可视化过程中,要求精细度高,这种需求还是其用武之地。
实现思路:要实现二级刻度,本质上和一级刻度的实现方法是一致的,故本文的实现方法主要参考echarts一级刻度的实现方法。即:首先根据二级刻度间隔计算在一个一级刻度内应该显示几个二级刻度,每一个二级刻度在图表上的相对坐标值,最后根据计算出的坐标值和配置项,在坐标轴上生成二级刻度。其实本质上每一个二级刻度线属于echarts的line
类的一个具体实例而已。
本文对于echarts刻度轴接口进行了扩展,作为axisTick的子接口,定义如下:
axisTick :{
secondTick: {
show: false,//是否显示二级刻度
interval: null,//二级刻度间间隔大小
length: 3,//二级刻度线的长度
lineStyle:{ //刻度线的线条样式
}
}
}
在二级刻度的实现过程中,有几个接口需要扩展:
(1)Axis.prototype原型中添加getSecondTicksCoords和dataToSecondCoord方法
/**
@params {Number} interval: 二级刻度间隔
@params {Array} ticks: 一级刻度的刻度值
*/
getSecondTicksCoords: function (interval, ticks) {
return zrUtil.map(this.scale.getSecondTicks && this.scale.getSecondTicks(interval, ticks) || [], this.dataToSecondCoord, this);
},
/**
主要进行映射,将刻度值映射在线性比例尺上,得到初始坐标轴
@params {Array} data: 二级刻度刻度值
*/
dataToSecondCoord: function (data) {
var extent = this._extent;
var scale = this.scale;
data = scale.normalize(data);
return linearMap(data, normalizedExtent, extent);
},
(2)在echarts的module中 echarts/scale/Interval添加,由于利用了intervalScaleGetTicks接口,故当二级刻度的个数超过10000条,会自动忽视,此时无法显示出二级刻度。因为二级刻度值超过10000条,本身也无意义。
getSecondTicks: function (interval, ticks) {
return helper.intervalScaleGetTicks(interval, ticks.slice(0, 2), ticks.slice(0, 2), this._intervalPrecision);
},
(3)通过echarts的graphic.Line接口生成二级刻度实线。此处可以利用一级刻度接口,如下是我,将一级刻度生成方法写的一个函数。
/**
绘制刻度
@param {Array} ticksCoords: 主要刻度坐标
@param {Number} tickLen: 刻度的长度
@param {Array} lineEls: 实际绘制的线条的存储数组
*/
function buildTicks(ticksCoords, tickLen, lineEls) {
var tickLine;
for (var i = 0; i < ticksCoords.length; i++) {
// Only ordinal scale support tick interval
if (ifIgnoreOnTick(axis, i, tickInterval)){
continue;
}
var tickCoord = ticksCoords[i];
pt1[0] = tickCoord;
pt1[1] = 0;
pt2[0] = tickCoord;
pt2[1] = opt.tickDirection * tickLen;
if (matrix) {
v2ApplyTransform(pt1, pt1, matrix);
v2ApplyTransform(pt2, pt2, matrix);
}
tickLine = new graphic.Line(graphic.subPixelOptimizeLine({
// Id for animation
anid: 'tick_' + ticks[i],
shape: {
x1: pt1[0],
y1: pt1[1],
x2: pt2[0],
y2: pt2[1]
},
style: zrUtil.defaults(
lineStyleModel.getLineStyle(),
{
stroke: axisModel.get('axisLine.lineStyle.color')
}
),
z2: 2,
silent: true
}));
lineEls.push(tickLine);
// Tick line, Not use group transform to have better line draw
this.group.add(tickLine);
}
}
(4)处理二级刻度配置项,代码如下所示:
if (axisModel.get('axisTick.secondTick.show')) {
var secondTickInterval = axisModel.get('axisTick.secondTick.interval');
var secondTickLength = axisModel.get('axisTick.secondTick.length');
var secondTicksCoords = axis.getSecondTicksCoords && axis.getSecondTicksCoords(secondTickInterval, ticks);
secondTicksCoords = initSecondTicksCoords(ticksCoords, secondTicksCoords);
buildTicks.call(this, secondTicksCoords, secondTickLength, lineEls);
}
/**
初始化次要刻度值
@param {Array} ticksCoords:主要刻度坐标
@param {Array} secondTicksCoords: 次要刻度坐标
@return {Array}返回实际绘制需要的坐标值
*/
function initSecondTicksCoords(ticksCoords, secondTicksCoords) {
var coords = [];
for (var i = 0; i < ticksCoords.length - 1; i++) {
for (var j = 1; j < secondTicksCoords.length - 1; j++) {
coords.push(ticksCoords[i] + secondTicksCoords[j]);
}
}
return coords;
}
以上就是主要的扩展方法,有兴趣的童鞋可以试试。
最后,附上一张效果图。