2021SC@SDUSC
直角坐标轴
Axis为直角坐标系Grid中的坐标轴,包括xAxis(x轴)以及yAxis(y轴)。
AxisModel
AxisModel通过extend方法扩展自Component Model,重写了init、mergeOption等方法,并使用AxisModelCreator分别创建xAxisModel以及yAxisModel
CartesianAxisView
CartesianAxisView通过extend方法扩展自AxisView,重写了render方法,定义了splitLine以及splitArea方法,并扩展了xAxis以及yAxis View。主要代码如下:
var CartesianAxisView = AxisView.extend({
type: 'cartesianAxis',
axisPointerClass: 'CartesianAxisPointer',
render: function (axisModel, ecModel, api, payload) {
...
// 结合AxisBuilder
var axisBuilder = new AxisBuilder(axisModel, layout);
zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder);
...
CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
},
...
_splitLine: function (axisModel, gridModel) {
...
// Simple optimization
// Batching the lines if color are the same
for (var i = 0; i < ticksCoords.length; i++) {
...
this._axisGroup.add(new graphic.Line(graphic.subPixelOptimizeLine({
anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null,
shape: {
x1: p1[0],
y1: p1[1],
x2: p2[0],
y2: p2[1]
},
style: zrUtil.defaults({
stroke: lineColors[colorIndex]
}, lineStyle),
silent: true
})));
}
},
_splitArea: function (axisModel, gridModel) {
...
for (var i = 1; i < ticksCoords.length; i++) {
...
this._axisGroup.add(new graphic.Rect({
anid: tickValue != null ? 'area_' + tickValue : null,
shape: {
x: x,
y: y,
width: width,
height: height
},
style: zrUtil.defaults({
fill: areaColors[colorIndex]
}, areaStyle),
silent: true
}));
colorIndex = (colorIndex + 1) % areaColorsLen;
}
this._splitAreaColors = newSplitAreaColors;
}
});
CartesianAxisView.extend({
type: 'xAxis'
});
CartesianAxisView.extend({
type: 'yAxis'
});
极坐标轴 AngleAxis&RadiusAxis
ECharts 图表的极坐标系(polar),可以在散点图和折线图中使用。
每一个极坐标都拥有一个角度轴AngleAxis和一个半径轴RadiusAxis。
配置
polar.zlevel:得到 ECharts 中极坐标系所有图形的 zlevel 值。
zlevel 用于 Canvas 分层,不同 zlevel 值的图形会放置在不同的 Canvas 中,Canvas 分层是一种常见的优化手段。我们可以把一些图形变化频繁(例如有动画)的组件设置成一个单独的zlevel。zlevel 大的 Canvas 会放在 zlevel 小的 Canvas 的上面。
polar.z:得到 ECharts 中极坐标系所有图形的 z 值。控制图形的前后顺序,z 值小的图形会被 z 值大的图形覆盖。z 相比 zlevel 优先级更低,而且不会创建新的 Canvas。
polar.center:得到极坐标系的中心(圆心)坐标,数组的第一项是横坐标,第二项是纵坐标。可以设置成百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高度。
polar.radius:得到极坐标系的半径,数组的第一项是内半径,第二项是外半径。支持设置成百分比,相对于容器高宽中较小的一项的一半。
公共文件
AxisModel通过extend方法扩展自Component Model,定义了getCoordSysModel方法,并根据不同option创建了angle和radius Model,主要代码如下:
axisModelCreator('angle', PolarAxisModel, getAxisType, polarAxisDefaultExtendedOption.angle);
axisModelCreator('radius', PolarAxisModel, getAxisType, polarAxisDefaultExtendedOption.radius);
角度轴 AngleAxis
AngleAxis为极坐标Polar中的角度轴。
AngleAxisView
AngleAxisView通过extend方法扩展自AxisView,重写了render方法,并定义了axisLine、axisTick、axisLabel、splitLine以及splitArea等方法,主要代码如下:
render: function (angleAxisModel, ecModel) {
...
var angleAxis = angleAxisModel.axis;
var polar = angleAxis.polar;
var radiusExtent = polar.getRadiusAxis().getExtent();
var ticksAngles = angleAxis.getTicksCoords();
var labels = zrUtil.map(angleAxis.getViewLabels(), function (labelItem) {
var labelItem = zrUtil.clone(labelItem);
labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
return labelItem;
});
...
},
_axisLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle');
var circle = new graphic.Circle({
shape: {
cx: polar.cx,
cy: polar.cy,
r: radiusExtent[getRadiusIdx(polar)]
},
style: lineStyleModel.getLineStyle(),
z2: 1,
silent: true
});
circle.style.fill = null;
this.group.add(circle);
},
_axisTick: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
var tickModel = angleAxisModel.getModel('axisTick');
var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
var radius = radiusExtent[getRadiusIdx(polar)];
var lines = zrUtil.map(ticksAngles, function (tickAngleItem) {
return new graphic.Line({
shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord)
});
});
this.group.add(graphic.mergePath(
lines, {
style: zrUtil.defaults(
tickModel.getModel('lineStyle').getLineStyle(),
{
stroke: angleAxisModel.get('axisLine.lineStyle.color')
}
)
}
));
},
_axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent, labels) {
...
// Use length of ticksAngles because it may remove the last tick to avoid overlapping
zrUtil.each(labels, function (labelItem, idx) {
...
var textEl = new graphic.Text({silent: true});
this.group.add(textEl);
graphic.setTextStyle(textEl.style, labelModel, {
x: p[0],
y: p[1],
textFill: labelModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'),
text: labelItem.formattedLabel,
textAlign: labelTextAlign,
textVerticalAlign: labelTextVerticalAlign
});
}, this);
},
_splitLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
...
for (var i = 0; i < ticksAngles.length; i++) {
var colorIndex = (lineCount++) % lineColors.length;
splitLines[colorIndex] = splitLines[colorIndex] || [];
splitLines[colorIndex].push(new graphic.Line({
shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord)
}));
}
// Simple optimization
// Batching the lines if color are the same
for (var i = 0; i < splitLines.length; i++) {
this.group.add(graphic.mergePath(splitLines[i], {
style: zrUtil.defaults({
stroke: lineColors[i % lineColors.length]
}, lineStyleModel.getLineStyle()),
silent: true,
z: angleAxisModel.get('z')
}));
}
},
_splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
...
for (var i = 1; i < ticksAngles.length; i++) {
var colorIndex = (lineCount++) % areaColors.length;
splitAreas[colorIndex] = splitAreas[colorIndex] || [];
splitAreas[colorIndex].push(new graphic.Sector({
shape: {
cx: polar.cx,
cy: polar.cy,
r0: r0,
r: r1,
startAngle: prevAngle,
endAngle: -ticksAngles[i].coord * RADIAN,
clockwise: clockwise
},
silent: true
}));
prevAngle = -ticksAngles[i].coord * RADIAN;
}
// Simple optimization
// Batching the lines if color are the same
for (var i = 0; i < splitAreas.length; i++) {
this.group.add(graphic.mergePath(splitAreas[i], {
style: zrUtil.defaults({
fill: areaColors[i % areaColors.length]
}, areaStyleModel.getAreaStyle()),
silent: true
}));
}
}
半径轴 RadiusAxis
RadiusAxis为极坐标Polar中的半径轴。
RadiusAxisView
RadiusAxisView通过extend方法扩展自AxisView,重写了render方法,并定义了splitLine、splitArea方法,主要代码如下:
_splitLine: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
...
for (var i = 0; i < ticksCoords.length; i++) {
var colorIndex = (lineCount++) % lineColors.length;
splitLines[colorIndex] = splitLines[colorIndex] || [];
splitLines[colorIndex].push(new graphic.Circle({
shape: {
cx: polar.cx,
cy: polar.cy,
r: ticksCoords[i].coord
},
silent: true
}));
}
// Simple optimization
// Batching the lines if color are the same
for (var i = 0; i < splitLines.length; i++) {
this.group.add(graphic.mergePath(splitLines[i], {
style: zrUtil.defaults({
stroke: lineColors[i % lineColors.length],
fill: null
}, lineStyleModel.getLineStyle()),
silent: true
}));
}
},
_splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
...
for (var i = 1; i < ticksCoords.length; i++) {
var colorIndex = (lineCount++) % areaColors.length;
splitAreas[colorIndex] = splitAreas[colorIndex] || [];
splitAreas[colorIndex].push(new graphic.Sector({
shape: {
cx: polar.cx,
cy: polar.cy,
r0: prevRadius,
r: ticksCoords[i].coord,
startAngle: 0,
endAngle: Math.PI * 2
},
silent: true
}));
prevRadius = ticksCoords[i].coord;
}
// Simple optimization
// Batching the lines if color are the same
for (var i = 0; i < splitAreas.length; i++) {
this.group.add(graphic.mergePath(splitAreas[i], {
style: zrUtil.defaults({
fill: areaColors[i % areaColors.length]
}, areaStyleModel.getAreaStyle()),
silent: true
}));
}
}