You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
804 lines
33 KiB
804 lines
33 KiB
/**
|
|
* echarts组件: 类目轴
|
|
*
|
|
* @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
|
|
* @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
|
|
*
|
|
*/
|
|
define(function (require) {
|
|
var Base = require('./base');
|
|
|
|
// 图形依赖
|
|
var TextShape = require('zrender/shape/Text');
|
|
var LineShape = require('zrender/shape/Line');
|
|
var RectangleShape = require('zrender/shape/Rectangle');
|
|
|
|
var ecConfig = require('../config');
|
|
// 类目轴
|
|
ecConfig.categoryAxis = {
|
|
zlevel: 0, // 一级层叠
|
|
z: 0, // 二级层叠
|
|
show: true,
|
|
position: 'bottom', // 位置
|
|
name: '', // 坐标轴名字,默认为空
|
|
nameLocation: 'end', // 坐标轴名字位置,支持'start' | 'end'
|
|
nameTextStyle: {}, // 坐标轴文字样式,默认取全局样式
|
|
boundaryGap: true, // 类目起始和结束两端空白策略
|
|
axisLine: { // 坐标轴线
|
|
show: true, // 默认显示,属性show控制显示与否
|
|
onZero: true,
|
|
lineStyle: { // 属性lineStyle控制线条样式
|
|
color: '#48b',
|
|
width: 2,
|
|
type: 'solid'
|
|
}
|
|
},
|
|
axisTick: { // 坐标轴小标记
|
|
show: true, // 属性show控制显示与否,默认不显示
|
|
interval: 'auto',
|
|
inside: false, // 控制小标记是否在grid里
|
|
// onGap: null,
|
|
length :5, // 属性length控制线长
|
|
lineStyle: { // 属性lineStyle控制线条样式
|
|
color: '#333',
|
|
width: 1
|
|
}
|
|
},
|
|
axisLabel: { // 坐标轴文本标签,详见axis.axisLabel
|
|
show: true,
|
|
interval: 'auto',
|
|
rotate: 0,
|
|
margin: 8,
|
|
// clickable: false,
|
|
// formatter: null,
|
|
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
|
|
color: '#333'
|
|
}
|
|
},
|
|
splitLine: { // 分隔线
|
|
show: true, // 默认显示,属性show控制显示与否
|
|
// onGap: null,
|
|
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
|
|
color: ['#ccc'],
|
|
width: 1,
|
|
type: 'solid'
|
|
}
|
|
},
|
|
splitArea: { // 分隔区域
|
|
show: false, // 默认不显示,属性show控制显示与否
|
|
// onGap: null,
|
|
areaStyle: { // 属性areaStyle(详见areaStyle)控制区域样式
|
|
color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)']
|
|
}
|
|
}
|
|
};
|
|
|
|
var zrUtil = require('zrender/tool/util');
|
|
var zrArea = require('zrender/tool/area');
|
|
|
|
/**
|
|
* 构造函数
|
|
* @param {Object} messageCenter echart消息中心
|
|
* @param {ZRender} zr zrender实例
|
|
* @param {Object} option 类目轴参数
|
|
* @param {Grid} component 组件
|
|
*/
|
|
function CategoryAxis(ecTheme, messageCenter, zr, option, myChart, axisBase) {
|
|
if (option.data.length < 1) {
|
|
console.error('option.data.length < 1.');
|
|
return;
|
|
}
|
|
|
|
Base.call(this, ecTheme, messageCenter, zr, option, myChart);
|
|
|
|
this.grid = this.component.grid;
|
|
|
|
for (var method in axisBase) {
|
|
this[method] = axisBase[method];
|
|
}
|
|
|
|
this.refresh(option);
|
|
}
|
|
|
|
CategoryAxis.prototype = {
|
|
type : ecConfig.COMPONENT_TYPE_AXIS_CATEGORY,
|
|
_getReformedLabel : function (idx) {
|
|
var data = this.getDataFromOption(this.option.data[idx]);
|
|
var formatter = this.option.data[idx].formatter
|
|
|| this.option.axisLabel.formatter;
|
|
if (formatter) {
|
|
if (typeof formatter == 'function') {
|
|
data = formatter.call(this.myChart, data);
|
|
}
|
|
else if (typeof formatter == 'string') {
|
|
data = formatter.replace('{value}', data);
|
|
}
|
|
}
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* 计算标签显示挑选间隔
|
|
*/
|
|
_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;
|
|
}
|
|
}
|
|
else {
|
|
// 纵向
|
|
if (dataLength > 3) {
|
|
var gap = this.getGap();
|
|
interval = Math.floor(11 / gap);
|
|
// 标签上下至少间隔为3px
|
|
while ((gap * interval - 6) < fontSize
|
|
&& interval < dataLength
|
|
) {
|
|
interval++;
|
|
}
|
|
}
|
|
else {
|
|
// 少于3个则全部显示
|
|
interval = 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// 用户自定义间隔,支持funtion
|
|
interval = typeof interval == 'function' ? 1 : (interval - 0 + 1);
|
|
}
|
|
|
|
return interval;
|
|
},
|
|
|
|
/**
|
|
* 绘制图形
|
|
*/
|
|
_buildShape : function () {
|
|
// 标签显示的挑选间隔
|
|
this._interval = this._getInterval();
|
|
if (!this.option.show) {
|
|
return;
|
|
}
|
|
this.option.splitArea.show && this._buildSplitArea();
|
|
this.option.splitLine.show && this._buildSplitLine();
|
|
this.option.axisLine.show && this._buildAxisLine();
|
|
this.option.axisTick.show && this._buildAxisTick();
|
|
this.option.axisLabel.show && this._buildAxisLabel();
|
|
|
|
for (var i = 0, l = this.shapeList.length; i < l; i++) {
|
|
this.zr.addShape(this.shapeList[i]);
|
|
}
|
|
},
|
|
|
|
// 小标记
|
|
_buildAxisTick : function () {
|
|
var axShape;
|
|
var data = this.option.data;
|
|
var dataLength = this.option.data.length;
|
|
var tickOption = this.option.axisTick;
|
|
var length = tickOption.length;
|
|
var color = tickOption.lineStyle.color;
|
|
var lineWidth = tickOption.lineStyle.width;
|
|
var intervalFunction = typeof tickOption.interval == 'function'
|
|
? tickOption.interval
|
|
: tickOption.interval == 'auto'
|
|
? typeof this.option.axisLabel.interval == 'function'
|
|
? this.option.axisLabel.interval : false
|
|
: false;
|
|
var interval = intervalFunction
|
|
? 1
|
|
: tickOption.interval == 'auto'
|
|
? this._interval
|
|
: (tickOption.interval - 0 + 1);
|
|
var onGap = tickOption.onGap;
|
|
var optGap = onGap
|
|
? (this.getGap() / 2)
|
|
: typeof onGap == 'undefined'
|
|
? (this.option.boundaryGap ? (this.getGap() / 2) : 0)
|
|
: 0;
|
|
var startIndex = optGap > 0 ? -interval : 0;
|
|
if (this.isHorizontal()) {
|
|
// 横向
|
|
var yPosition = this.option.position == 'bottom'
|
|
? (tickOption.inside
|
|
? (this.grid.getYend() - length - 1) : (this.grid.getYend() + 1))
|
|
: (tickOption.inside
|
|
? (this.grid.getY() + 1) : (this.grid.getY() - length - 1));
|
|
var x;
|
|
for (var i = startIndex; i < dataLength; i += interval) {
|
|
if (intervalFunction && !intervalFunction(i, data[i])) {
|
|
// 回调并且回调返回false则跳过渲染
|
|
continue;
|
|
}
|
|
// 亚像素优化
|
|
x = this.subPixelOptimize(
|
|
this.getCoordByIndex(i) + (i >= 0 ? optGap : 0), lineWidth
|
|
);
|
|
axShape = {
|
|
_axisShape : 'axisTick',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
xStart : x,
|
|
yStart : yPosition,
|
|
xEnd : x,
|
|
yEnd : yPosition + length,
|
|
strokeColor : color,
|
|
lineWidth : lineWidth
|
|
}
|
|
};
|
|
this.shapeList.push(new LineShape(axShape));
|
|
}
|
|
}
|
|
else {
|
|
// 纵向
|
|
var xPosition = this.option.position == 'left'
|
|
? (tickOption.inside
|
|
? (this.grid.getX() + 1) : (this.grid.getX() - length - 1))
|
|
: (tickOption.inside
|
|
? (this.grid.getXend() - length - 1) : (this.grid.getXend() + 1));
|
|
|
|
var y;
|
|
for (var i = startIndex; i < dataLength; i += interval) {
|
|
if (intervalFunction && !intervalFunction(i, data[i])) {
|
|
// 回调并且回调返回false则中断渲染
|
|
continue;
|
|
}
|
|
// 亚像素优化
|
|
y = this.subPixelOptimize(
|
|
this.getCoordByIndex(i) - (i >= 0 ? optGap : 0), lineWidth
|
|
);
|
|
axShape = {
|
|
_axisShape : 'axisTick',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
xStart : xPosition,
|
|
yStart : y,
|
|
xEnd : xPosition + length,
|
|
yEnd : y,
|
|
strokeColor : color,
|
|
lineWidth : lineWidth
|
|
}
|
|
};
|
|
this.shapeList.push(new LineShape(axShape));
|
|
}
|
|
}
|
|
},
|
|
|
|
// 坐标轴文本
|
|
_buildAxisLabel : function () {
|
|
var axShape;
|
|
var data = this.option.data;
|
|
var dataLength = this.option.data.length;
|
|
var labelOption = this.option.axisLabel;
|
|
var rotate = labelOption.rotate;
|
|
var margin = labelOption.margin;
|
|
var clickable = labelOption.clickable;
|
|
var textStyle = labelOption.textStyle;
|
|
var intervalFunction = typeof labelOption.interval == 'function'
|
|
? labelOption.interval : false;
|
|
var dataTextStyle;
|
|
|
|
if (this.isHorizontal()) {
|
|
// 横向
|
|
var yPosition;
|
|
var baseLine;
|
|
if (this.option.position == 'bottom') {
|
|
yPosition = this.grid.getYend() + margin;
|
|
baseLine = 'top';
|
|
}
|
|
else {
|
|
yPosition = this.grid.getY() - margin;
|
|
baseLine = 'bottom';
|
|
}
|
|
|
|
for (var i = 0; i < dataLength; i += this._interval) {
|
|
if ((intervalFunction && !intervalFunction(i, data[i]))
|
|
// 回调并且回调返回false则中断渲染
|
|
|| this._getReformedLabel(i) === '' // 空文本优化
|
|
) {
|
|
continue;
|
|
}
|
|
dataTextStyle = zrUtil.merge(
|
|
data[i].textStyle || {},
|
|
textStyle
|
|
);
|
|
axShape = {
|
|
// shape : 'text',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase() + 3,
|
|
hoverable : false,
|
|
style : {
|
|
x : this.getCoordByIndex(i),
|
|
y : yPosition,
|
|
color : dataTextStyle.color,
|
|
text : this._getReformedLabel(i),
|
|
textFont : this.getFont(dataTextStyle),
|
|
textAlign : dataTextStyle.align || 'center',
|
|
textBaseline : dataTextStyle.baseline || baseLine
|
|
}
|
|
};
|
|
if (rotate) {
|
|
axShape.style.textAlign = rotate > 0
|
|
? (this.option.position == 'bottom'
|
|
? 'right' : 'left')
|
|
: (this.option.position == 'bottom'
|
|
? 'left' : 'right');
|
|
axShape.rotation = [
|
|
rotate * Math.PI / 180,
|
|
axShape.style.x,
|
|
axShape.style.y
|
|
];
|
|
}
|
|
this.shapeList.push(new TextShape(
|
|
this._axisLabelClickable(clickable, axShape)
|
|
));
|
|
}
|
|
}
|
|
else {
|
|
// 纵向
|
|
var xPosition;
|
|
var align;
|
|
if (this.option.position == 'left') {
|
|
xPosition = this.grid.getX() - margin;
|
|
align = 'right';
|
|
}
|
|
else {
|
|
xPosition = this.grid.getXend() + margin;
|
|
align = 'left';
|
|
}
|
|
|
|
for (var i = 0; i < dataLength; i += this._interval) {
|
|
if ((intervalFunction && !intervalFunction(i, data[i]))
|
|
// 回调并且回调返回false则中断渲染
|
|
|| this._getReformedLabel(i) === '' // 空文本优化
|
|
) {
|
|
continue;
|
|
}
|
|
dataTextStyle = zrUtil.merge(
|
|
data[i].textStyle || {},
|
|
textStyle
|
|
);
|
|
axShape = {
|
|
// shape : 'text',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase() + 3,
|
|
hoverable : false,
|
|
style : {
|
|
x : xPosition,
|
|
y : this.getCoordByIndex(i),
|
|
color : dataTextStyle.color,
|
|
text : this._getReformedLabel(i),
|
|
textFont : this.getFont(dataTextStyle),
|
|
textAlign : dataTextStyle.align || align,
|
|
textBaseline : dataTextStyle.baseline
|
|
|| (i === 0 && this.option.name !== '')
|
|
? 'bottom'
|
|
: (i == (dataLength - 1)
|
|
&& this.option.name !== '')
|
|
? 'top'
|
|
: 'middle'
|
|
}
|
|
};
|
|
|
|
if (rotate) {
|
|
axShape.rotation = [
|
|
rotate * Math.PI / 180,
|
|
axShape.style.x,
|
|
axShape.style.y
|
|
];
|
|
}
|
|
this.shapeList.push(new TextShape(
|
|
this._axisLabelClickable(clickable, axShape)
|
|
));
|
|
}
|
|
}
|
|
},
|
|
|
|
_buildSplitLine : function () {
|
|
var axShape;
|
|
var data = this.option.data;
|
|
var dataLength = this.option.data.length;
|
|
var sLineOption = this.option.splitLine;
|
|
var lineType = sLineOption.lineStyle.type;
|
|
var lineWidth = sLineOption.lineStyle.width;
|
|
var color = sLineOption.lineStyle.color;
|
|
color = color instanceof Array ? color : [color];
|
|
var colorLength = color.length;
|
|
|
|
// splitLine随axisLable
|
|
var intervalFunction = typeof this.option.axisLabel.interval == 'function'
|
|
? this.option.axisLabel.interval : false;
|
|
|
|
var onGap = sLineOption.onGap;
|
|
var optGap = onGap
|
|
? (this.getGap() / 2)
|
|
: typeof onGap == 'undefined'
|
|
? (this.option.boundaryGap ? (this.getGap() / 2) : 0)
|
|
: 0;
|
|
dataLength -= (onGap || (typeof onGap == 'undefined' && this.option.boundaryGap))
|
|
? 1 : 0;
|
|
if (this.isHorizontal()) {
|
|
// 横向
|
|
var sy = this.grid.getY();
|
|
var ey = this.grid.getYend();
|
|
var x;
|
|
|
|
for (var i = 0; i < dataLength; i += this._interval) {
|
|
if (intervalFunction && !intervalFunction(i, data[i])) {
|
|
// 回调并且回调返回false则跳过渲染
|
|
continue;
|
|
}
|
|
// 亚像素优化
|
|
x = this.subPixelOptimize(
|
|
this.getCoordByIndex(i) + optGap, lineWidth
|
|
);
|
|
axShape = {
|
|
// shape : 'line',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
xStart : x,
|
|
yStart : sy,
|
|
xEnd : x,
|
|
yEnd : ey,
|
|
strokeColor : color[(i / this._interval) % colorLength],
|
|
lineType : lineType,
|
|
lineWidth : lineWidth
|
|
}
|
|
};
|
|
this.shapeList.push(new LineShape(axShape));
|
|
}
|
|
|
|
}
|
|
else {
|
|
// 纵向
|
|
var sx = this.grid.getX();
|
|
var ex = this.grid.getXend();
|
|
var y;
|
|
|
|
for (var i = 0; i < dataLength; i += this._interval) {
|
|
if (intervalFunction && !intervalFunction(i, data[i])) {
|
|
// 回调并且回调返回false则跳过渲染
|
|
continue;
|
|
}
|
|
// 亚像素优化
|
|
y = this.subPixelOptimize(
|
|
this.getCoordByIndex(i) - optGap, lineWidth
|
|
);
|
|
axShape = {
|
|
// shape : 'line',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
xStart : sx,
|
|
yStart : y,
|
|
xEnd : ex,
|
|
yEnd : y,
|
|
strokeColor : color[(i / this._interval) % colorLength],
|
|
lineType : lineType,
|
|
lineWidth : lineWidth
|
|
}
|
|
};
|
|
this.shapeList.push(new LineShape(axShape));
|
|
}
|
|
}
|
|
},
|
|
|
|
_buildSplitArea : function () {
|
|
var axShape;
|
|
var data = this.option.data;
|
|
var sAreaOption = this.option.splitArea;
|
|
var color = sAreaOption.areaStyle.color;
|
|
if (!(color instanceof Array)) {
|
|
// 非数组一律认为是单一颜色的字符串,单一颜色则用一个背景,颜色错误不负责啊!!!
|
|
axShape = {
|
|
// shape : 'rectangle',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
x : this.grid.getX(),
|
|
y : this.grid.getY(),
|
|
width : this.grid.getWidth(),
|
|
height : this.grid.getHeight(),
|
|
color : color
|
|
// type : this.option.splitArea.areaStyle.type,
|
|
}
|
|
};
|
|
this.shapeList.push(new RectangleShape(axShape));
|
|
}
|
|
else {
|
|
// 多颜色
|
|
var colorLength = color.length;
|
|
var dataLength = this.option.data.length;
|
|
|
|
// splitArea随axisLable
|
|
var intervalFunction = typeof this.option.axisLabel.interval == 'function'
|
|
? this.option.axisLabel.interval : false;
|
|
|
|
var onGap = sAreaOption.onGap;
|
|
var optGap = onGap
|
|
? (this.getGap() / 2)
|
|
: typeof onGap == 'undefined'
|
|
? (this.option.boundaryGap ? (this.getGap() / 2) : 0)
|
|
: 0;
|
|
if (this.isHorizontal()) {
|
|
// 横向
|
|
var y = this.grid.getY();
|
|
var height = this.grid.getHeight();
|
|
var lastX = this.grid.getX();
|
|
var curX;
|
|
|
|
for (var i = 0; i <= dataLength; i += this._interval) {
|
|
if (intervalFunction && !intervalFunction(i, data[i]) && i < dataLength) {
|
|
// 回调并且回调返回false则跳过渲染
|
|
continue;
|
|
}
|
|
curX = i < dataLength
|
|
? (this.getCoordByIndex(i) + optGap)
|
|
: this.grid.getXend();
|
|
axShape = {
|
|
// shape : 'rectangle',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
x : lastX,
|
|
y : y,
|
|
width : curX - lastX,
|
|
height : height,
|
|
color : color[(i / this._interval) % colorLength]
|
|
// type : this.option.splitArea.areaStyle.type,
|
|
}
|
|
};
|
|
this.shapeList.push(new RectangleShape(axShape));
|
|
lastX = curX;
|
|
}
|
|
}
|
|
else {
|
|
// 纵向
|
|
var x = this.grid.getX();
|
|
var width = this.grid.getWidth();
|
|
var lastYend = this.grid.getYend();
|
|
var curY;
|
|
|
|
for (var i = 0; i <= dataLength; i += this._interval) {
|
|
if (intervalFunction && !intervalFunction(i, data[i]) && i < dataLength) {
|
|
// 回调并且回调返回false则跳过渲染
|
|
continue;
|
|
}
|
|
curY = i < dataLength
|
|
? (this.getCoordByIndex(i) - optGap)
|
|
: this.grid.getY();
|
|
axShape = {
|
|
// shape : 'rectangle',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable : false,
|
|
style : {
|
|
x : x,
|
|
y : curY,
|
|
width : width,
|
|
height : lastYend - curY,
|
|
color : color[(i / this._interval) % colorLength]
|
|
// type : this.option.splitArea.areaStyle.type
|
|
}
|
|
};
|
|
this.shapeList.push(new RectangleShape(axShape));
|
|
lastYend = curY;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 刷新
|
|
*/
|
|
refresh : function (newOption) {
|
|
if (newOption) {
|
|
this.option = this.reformOption(newOption);
|
|
// 通用字体设置
|
|
this.option.axisLabel.textStyle = this.getTextStyle(
|
|
this.option.axisLabel.textStyle
|
|
);
|
|
}
|
|
this.clear();
|
|
this._buildShape();
|
|
},
|
|
|
|
/**
|
|
* 返回间隔
|
|
*/
|
|
getGap : function () {
|
|
var dataLength = this.option.data.length;
|
|
var total = this.isHorizontal()
|
|
? this.grid.getWidth()
|
|
: this.grid.getHeight();
|
|
if (this.option.boundaryGap) { // 留空
|
|
return total / dataLength;
|
|
}
|
|
else { // 顶头
|
|
return total / (dataLength > 1 ? (dataLength - 1) : 1);
|
|
}
|
|
},
|
|
|
|
// 根据值换算位置
|
|
getCoord : function (value) {
|
|
var data = this.option.data;
|
|
var dataLength = data.length;
|
|
var gap = this.getGap();
|
|
var position = this.option.boundaryGap ? (gap / 2) : 0;
|
|
|
|
for (var i = 0; i < dataLength; i++) {
|
|
if (this.getDataFromOption(data[i]) == value) {
|
|
if (this.isHorizontal()) {
|
|
// 横向
|
|
position = this.grid.getX() + position;
|
|
}
|
|
else {
|
|
// 纵向
|
|
position = this.grid.getYend() - position;
|
|
}
|
|
|
|
return position;
|
|
// Math.floor可能引起一些偏差,但性能会更好
|
|
/* 准确更重要
|
|
return (i === 0 || i == dataLength - 1)
|
|
? position
|
|
: Math.floor(position);
|
|
*/
|
|
}
|
|
position += gap;
|
|
}
|
|
},
|
|
|
|
// 根据类目轴数据索引换算位置
|
|
getCoordByIndex : function (dataIndex) {
|
|
if (dataIndex < 0) {
|
|
if (this.isHorizontal()) {
|
|
return this.grid.getX();
|
|
}
|
|
else {
|
|
return this.grid.getYend();
|
|
}
|
|
}
|
|
else if (dataIndex > this.option.data.length - 1) {
|
|
if (this.isHorizontal()) {
|
|
return this.grid.getXend();
|
|
}
|
|
else {
|
|
return this.grid.getY();
|
|
}
|
|
}
|
|
else {
|
|
var gap = this.getGap();
|
|
var position = this.option.boundaryGap ? (gap / 2) : 0;
|
|
position += dataIndex * gap;
|
|
|
|
if (this.isHorizontal()) {
|
|
// 横向
|
|
position = this.grid.getX() + position;
|
|
}
|
|
else {
|
|
// 纵向
|
|
position = this.grid.getYend() - position;
|
|
}
|
|
|
|
return position;
|
|
/* 准确更重要
|
|
return (dataIndex === 0 || dataIndex == this.option.data.length - 1)
|
|
? position
|
|
: Math.floor(position);
|
|
*/
|
|
}
|
|
},
|
|
|
|
// 根据类目轴数据索引换算类目轴名称
|
|
getNameByIndex : function (dataIndex) {
|
|
return this.getDataFromOption(this.option.data[dataIndex]);
|
|
},
|
|
|
|
// 根据类目轴名称换算类目轴数据索引
|
|
getIndexByName : function (name) {
|
|
var data = this.option.data;
|
|
var dataLength = data.length;
|
|
|
|
for (var i = 0; i < dataLength; i++) {
|
|
if (this.getDataFromOption(data[i]) == name) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
},
|
|
|
|
// 根据位置换算值
|
|
getValueFromCoord : function() {
|
|
return '';
|
|
},
|
|
|
|
/**
|
|
* 根据类目轴数据索引返回是否为主轴线
|
|
* @param {number} dataIndex 类目轴数据索引
|
|
* @return {boolean} 是否为主轴
|
|
*/
|
|
isMainAxis : function (dataIndex) {
|
|
return dataIndex % this._interval === 0;
|
|
}
|
|
};
|
|
|
|
zrUtil.inherits(CategoryAxis, Base);
|
|
|
|
require('../component').define('categoryAxis', CategoryAxis);
|
|
|
|
return CategoryAxis;
|
|
});
|