提交 748f33eb 编写于 作者: S sushuang

(1) Some refactor about axisTick, axisLabel, splitLine, splitArea interval...

(1) Some refactor about axisTick, axisLabel, splitLine, splitArea interval logic: arrange and uniform the API, about 'ifIgnoreOnTick', 'isLabelIgnored', 'getTicksCoords',  'getLabelsCoords', etc. Fixed the inconsistent calling of user specified "axis interval" function.
(2) Make the choice of axisTick, axisLabel, splitLine, splitArea be stable when category axis auto interval exists and moving by dataZoom.
(3) Make the animation appropriate for label, ticks, splitLine, splitArea when view window moving (by dataZoom) in category axis.
上级 a8ef1835
......@@ -605,15 +605,26 @@ export default ChartView.extend({
this._polygon = polygon;
return polygon;
},
/**
* @private
*/
_getSymbolIgnoreFunc: function (data, coordSys) {
var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
// `getLabelInterval` is provided by echarts/component/axis
if (categoryAxis && categoryAxis.isLabelIgnored) {
return zrUtil.bind(categoryAxis.isLabelIgnored, categoryAxis);
if (!categoryAxis) {
return;
}
var categoryDataDim = data.mapDimension(categoryAxis.dim);
var labelMap = {};
zrUtil.each(categoryAxis.getViewLabels(), function (labelItem) {
labelMap[labelItem.tickValue] = 1;
});
return function (dataIndex) {
return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex));
};
},
/**
......
......@@ -23,6 +23,18 @@ function getRadiusIdx(polar) {
return radiusAxis.inverse ? 0 : 1;
}
// Remove the last tick which will overlap the first tick
function fixAngleOverlap(list) {
var firstItem = list[0];
var lastItem = list[list.length - 1];
if (firstItem
&& lastItem
&& Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4
) {
list.pop();
}
}
export default AxisView.extend({
type: 'angleAxis',
......@@ -38,18 +50,22 @@ export default AxisView.extend({
var angleAxis = angleAxisModel.axis;
var polar = angleAxis.polar;
var radiusExtent = polar.getRadiusAxis().getExtent();
var ticksAngles = angleAxis.getTicksCoords();
var labels = angleAxis.getViewLabels();
if (angleAxis.type !== 'category') {
// Remove the last tick which will overlap the first tick
ticksAngles.pop();
}
zrUtil.each(labels, function (labelItem) {
labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
});
fixAngleOverlap(labels);
fixAngleOverlap(ticksAngles);
zrUtil.each(elementList, function (name) {
if (angleAxisModel.get(name +'.show')
&& (!angleAxis.scale.isBlank() || name === 'axisLine')
) {
this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent);
this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent, labels);
}
}, this);
},
......@@ -84,9 +100,9 @@ export default AxisView.extend({
var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
var radius = radiusExtent[getRadiusIdx(polar)];
var lines = zrUtil.map(ticksAngles, function (tickAngle) {
var lines = zrUtil.map(ticksAngles, function (tickAngleItem) {
return new graphic.Line({
shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngle)
shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord)
});
});
this.group.add(graphic.mergePath(
......@@ -104,24 +120,20 @@ export default AxisView.extend({
/**
* @private
*/
_axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
var axis = angleAxisModel.axis;
_axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent, labels) {
var rawCategoryData = angleAxisModel.getCategories(true);
var commonLabelModel = angleAxisModel.getModel('axisLabel');
var labels = angleAxisModel.getFormattedLabels();
var labelMargin = commonLabelModel.get('margin');
var labelsAngles = axis.getLabelsCoords();
var ticks = axis.scale.getTicks();
// Use length of ticksAngles because it may remove the last tick to avoid overlapping
for (var i = 0; i < ticks.length; i++) {
zrUtil.each(labels, function (labelItem, idx) {
var labelModel = commonLabelModel;
var tickVal = ticks[i];
var tickValue = labelItem.tickValue;
var r = radiusExtent[getRadiusIdx(polar)];
var p = polar.coordToPoint([r + labelMargin, labelsAngles[i]]);
var p = polar.coordToPoint([r + labelMargin, labelItem.coord]);
var cx = polar.cx;
var cy = polar.cy;
......@@ -130,8 +142,8 @@ export default AxisView.extend({
var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3
? 'middle' : (p[1] > cy ? 'top' : 'bottom');
if (rawCategoryData && rawCategoryData[tickVal] && rawCategoryData[tickVal].textStyle) {
labelModel = new Model(rawCategoryData[tickVal].textStyle, commonLabelModel, commonLabelModel.ecModel);
if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
labelModel = new Model(rawCategoryData[tickValue].textStyle, commonLabelModel, commonLabelModel.ecModel);
}
var textEl = new graphic.Text({silent: true});
......@@ -140,11 +152,11 @@ export default AxisView.extend({
x: p[0],
y: p[1],
textFill: labelModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'),
text: labels[i],
text: labelItem.formattedLabel,
textAlign: labelTextAlign,
textVerticalAlign: labelTextVerticalAlign
});
}
}, this);
},
/**
......@@ -164,7 +176,7 @@ export default AxisView.extend({
var colorIndex = (lineCount++) % lineColors.length;
splitLines[colorIndex] = splitLines[colorIndex] || [];
splitLines[colorIndex].push(new graphic.Line({
shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i])
shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord)
}));
}
......@@ -185,6 +197,9 @@ export default AxisView.extend({
* @private
*/
_splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
if (!ticksAngles.length) {
return;
}
var splitAreaModel = angleAxisModel.getModel('splitArea');
var areaStyleModel = splitAreaModel.getModel('areaStyle');
......@@ -196,7 +211,7 @@ export default AxisView.extend({
var splitAreas = [];
var RADIAN = Math.PI / 180;
var prevAngle = -ticksAngles[0] * RADIAN;
var prevAngle = -ticksAngles[0].coord * RADIAN;
var r0 = Math.min(radiusExtent[0], radiusExtent[1]);
var r1 = Math.max(radiusExtent[0], radiusExtent[1]);
......@@ -212,12 +227,12 @@ export default AxisView.extend({
r0: r0,
r: r1,
startAngle: prevAngle,
endAngle: -ticksAngles[i] * RADIAN,
endAngle: -ticksAngles[i].coord * RADIAN,
clockwise: clockwise
},
silent: true
}));
prevAngle = -ticksAngles[i] * RADIAN;
prevAngle = -ticksAngles[i].coord * RADIAN;
}
// Simple optimization
......
......@@ -53,8 +53,6 @@ function makeAxisEventDataBase(axisModel) {
* @param {string} [opt.axisName] default get from axisModel.
* @param {number} [opt.axisNameAvailableWidth]
* @param {number} [opt.labelRotate] by degree, default get from axisModel.
* @param {number} [opt.labelInterval] Default label interval when label
* interval from model is null or 'auto'.
* @param {number} [opt.strokeContainThreshold] Default label interval when label
* @param {number} [opt.nameTruncateMaxWidth]
*/
......@@ -542,48 +540,6 @@ function isNameLocationCenter(nameLocation) {
return nameLocation === 'middle' || nameLocation === 'center';
}
/**
* @static
*/
var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick = function (
axis,
i,
interval,
ticksCnt,
showMinLabel,
showMaxLabel
) {
if (i === 0 && showMinLabel || i === ticksCnt - 1 && showMaxLabel) {
return false;
}
// FIXME
// Have not consider label overlap (if label is too long) yet.
var rawTick;
var scale = axis.scale;
return scale.type === 'ordinal'
&& (
typeof interval === 'function'
? (
rawTick = scale.getTicks()[i],
!interval(rawTick, scale.getLabel(rawTick))
)
: i % (interval + 1)
);
};
/**
* @static
*/
var getInterval = AxisBuilder.getInterval = function (model, labelInterval) {
var interval = model.get('interval');
if (interval == null || interval == 'auto') {
interval = labelInterval;
}
return interval;
};
function buildAxisTick(axisBuilder, axisModel, opt) {
var axis = axisModel.axis;
......@@ -596,14 +552,7 @@ function buildAxisTick(axisBuilder, axisModel, opt) {
var lineStyleModel = tickModel.getModel('lineStyle');
var tickLen = tickModel.get('length');
var tickInterval = getInterval(tickModel, opt.labelInterval);
var ticksCoords = axis.getTicksCoords(tickModel.get('alignWithLabel'));
// FIXME
// Corresponds to ticksCoords ?
var ticks = axis.scale.getTicks();
var showMinLabel = axisModel.get('axisLabel.showMinLabel');
var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');
var ticksCoords = axis.getTicksCoords();
var pt1 = [];
var pt2 = [];
......@@ -611,17 +560,8 @@ function buildAxisTick(axisBuilder, axisModel, opt) {
var tickEls = [];
var ticksCnt = ticksCoords.length;
for (var i = 0; i < ticksCnt; i++) {
// Only ordinal scale support tick interval
if (ifIgnoreOnTick(
axis, i, tickInterval, ticksCnt,
showMinLabel, showMaxLabel
)) {
continue;
}
var tickCoord = ticksCoords[i];
for (var i = 0; i < ticksCoords.length; i++) {
var tickCoord = ticksCoords[i].coord;
pt1[0] = tickCoord;
pt1[1] = 0;
......@@ -635,7 +575,7 @@ function buildAxisTick(axisBuilder, axisModel, opt) {
// Tick line, Not use group transform to have better line draw
var tickEl = new graphic.Line(graphic.subPixelOptimizeLine({
// Id for animation
anid: 'tick_' + ticks[i],
anid: 'tick_' + ticksCoords[i].tickValue,
shape: {
x1: pt1[0],
......@@ -669,8 +609,7 @@ function buildAxisLabel(axisBuilder, axisModel, opt) {
var labelModel = axisModel.getModel('axisLabel');
var labelMargin = labelModel.get('margin');
var ticks = axis.scale.getTicks();
var labels = axisModel.getFormattedLabels();
var labels = axis.getViewLabels();
// Special label rotate.
var labelRotation = (
......@@ -684,37 +623,30 @@ function buildAxisLabel(axisBuilder, axisModel, opt) {
var silent = isSilent(axisModel);
var triggerEvent = axisModel.get('triggerEvent');
var showMinLabel = axisModel.get('axisLabel.showMinLabel');
var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');
each(ticks, function (tickVal, index) {
if (ifIgnoreOnTick(
axis, index, opt.labelInterval, ticks.length,
showMinLabel, showMaxLabel
)) {
return;
}
each(labels, function (labelItem, index) {
var tickValue = labelItem.tickValue;
var formattedLabel = labelItem.formattedLabel;
var rawLabel = labelItem.rawLabel;
var itemLabelModel = labelModel;
if (rawCategoryData && rawCategoryData[tickVal] && rawCategoryData[tickVal].textStyle) {
if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
itemLabelModel = new Model(
rawCategoryData[tickVal].textStyle, labelModel, axisModel.ecModel
rawCategoryData[tickValue].textStyle, labelModel, axisModel.ecModel
);
}
var textColor = itemLabelModel.getTextColor()
|| axisModel.get('axisLine.lineStyle.color');
var tickCoord = axis.dataToCoord(tickVal);
var tickCoord = axis.dataToCoord(tickValue);
var pos = [
tickCoord,
opt.labelOffset + opt.labelDirection * labelMargin
];
var labelStr = axis.scale.getLabel(tickVal);
var textEl = new graphic.Text({
// Id for animation
anid: 'label_' + tickVal,
anid: 'label_' + tickValue,
position: pos,
rotation: labelLayout.rotation,
silent: silent,
......@@ -722,7 +654,7 @@ function buildAxisLabel(axisBuilder, axisModel, opt) {
});
graphic.setTextStyle(textEl.style, itemLabelModel, {
text: labels[index],
text: formattedLabel,
textAlign: itemLabelModel.getShallow('align', true)
|| labelLayout.textAlign,
textVerticalAlign: itemLabelModel.getShallow('verticalAlign', true)
......@@ -733,11 +665,15 @@ function buildAxisLabel(axisBuilder, axisModel, opt) {
// (1) In category axis with data zoom, tick is not the original
// index of axis.data. So tick should not be exposed to user
// in category axis.
// (2) Compatible with previous version, which always returns labelStr.
// But in interval scale labelStr is like '223,445', which maked
// user repalce ','. So we modify it to return original val but remain
// (2) Compatible with previous version, which always use formatted label as
// input. But in interval scale the formatted label is like '223,445', which
// maked user repalce ','. So we modify it to return original val but remain
// it as 'string' to avoid error in replacing.
axis.type === 'category' ? labelStr : axis.type === 'value' ? tickVal + '' : tickVal,
axis.type === 'category'
? rawLabel
: axis.type === 'value'
? tickValue + ''
: tickValue,
index
)
: textColor
......@@ -747,7 +683,7 @@ function buildAxisLabel(axisBuilder, axisModel, opt) {
if (triggerEvent) {
textEl.eventData = makeAxisEventDataBase(axisModel);
textEl.eventData.targetType = 'axisLabel';
textEl.eventData.value = labelStr;
textEl.eventData.value = rawLabel;
}
// FIXME
......
......@@ -2,10 +2,7 @@ import * as zrUtil from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
import AxisBuilder from './AxisBuilder';
import AxisView from './AxisView';
import * as cartesianAxisHelper from './cartesianAxisHelper';
var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick;
var getInterval = AxisBuilder.getInterval;
import * as cartesianAxisHelper from '../../coord/cartesian/cartesianAxisHelper';
var axisBuilderAttrs = [
'axisLine', 'axisTickLabel', 'axisName'
......@@ -56,7 +53,7 @@ var CartesianAxisView = AxisView.extend({
zrUtil.each(selfBuilderAttrs, function (name) {
if (axisModel.get(name + '.show')) {
this['_' + name](axisModel, gridModel, layout.labelInterval);
this['_' + name](axisModel, gridModel);
}
}, this);
......@@ -65,13 +62,16 @@ var CartesianAxisView = AxisView.extend({
CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
},
remove: function () {
this._splitAreaColors = null;
},
/**
* @param {module:echarts/coord/cartesian/AxisModel} axisModel
* @param {module:echarts/coord/cartesian/GridModel} gridModel
* @param {number|Function} labelInterval
* @private
*/
_splitLine: function (axisModel, gridModel, labelInterval) {
_splitLine: function (axisModel, gridModel) {
var axis = axisModel.axis;
if (axis.scale.isBlank()) {
......@@ -82,8 +82,6 @@ var CartesianAxisView = AxisView.extend({
var lineStyleModel = splitLineModel.getModel('lineStyle');
var lineColors = lineStyleModel.get('color');
var lineInterval = getInterval(splitLineModel, labelInterval);
lineColors = zrUtil.isArray(lineColors) ? lineColors : [lineColors];
var gridRect = gridModel.coordinateSystem.getRect();
......@@ -91,28 +89,18 @@ var CartesianAxisView = AxisView.extend({
var lineCount = 0;
var ticksCoords = axis.getTicksCoords(
// splitLineModel.get('alignWithLabel')
);
var ticks = axis.scale.getTicks();
var showMinLabel = axisModel.get('axisLabel.showMinLabel');
var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');
var ticksCoords = axis.getTicksCoords({
tickModel: splitLineModel
});
var p1 = [];
var p2 = [];
// Simple optimization
// Batching the lines if color are the same
var lineStyle = lineStyleModel.getLineStyle();
for (var i = 0; i < ticksCoords.length; i++) {
if (ifIgnoreOnTick(
axis, i, lineInterval, ticksCoords.length,
showMinLabel, showMaxLabel
)) {
continue;
}
var tickCoord = axis.toGlobalCoord(ticksCoords[i]);
var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
if (isHorizontal) {
p1[0] = tickCoord;
......@@ -129,8 +117,7 @@ var CartesianAxisView = AxisView.extend({
var colorIndex = (lineCount++) % lineColors.length;
this._axisGroup.add(new graphic.Line(graphic.subPixelOptimizeLine({
anid: 'line_' + ticks[i],
anid: 'line_' + ticksCoords[i].tickValue,
shape: {
x1: p1[0],
y1: p1[1],
......@@ -148,10 +135,9 @@ var CartesianAxisView = AxisView.extend({
/**
* @param {module:echarts/coord/cartesian/AxisModel} axisModel
* @param {module:echarts/coord/cartesian/GridModel} gridModel
* @param {number|Function} labelInterval
* @private
*/
_splitArea: function (axisModel, gridModel, labelInterval) {
_splitArea: function (axisModel, gridModel) {
var axis = axisModel.axis;
if (axis.scale.isBlank()) {
......@@ -164,55 +150,63 @@ var CartesianAxisView = AxisView.extend({
var gridRect = gridModel.coordinateSystem.getRect();
var ticksCoords = axis.getTicksCoords(
// splitAreaModel.get('alignWithLabel')
);
var ticks = axis.scale.getTicks();
var ticksCoords = axis.getTicksCoords({
tickModel: splitAreaModel,
clamp: true
});
var prevX = axis.toGlobalCoord(ticksCoords[0]);
var prevY = axis.toGlobalCoord(ticksCoords[0]);
if (!ticksCoords.length) {
return;
}
var count = 0;
// For Making appropriate splitArea animation, the color and anid
// should be corresponding to previous one if possible.
var areaColorsLen = areaColors.length;
var lastSplitAreaColors = this._splitAreaColors;
var newSplitAreaColors = zrUtil.createHashMap();
var colorIndex = 0;
if (lastSplitAreaColors) {
for (var i = 0; i < ticksCoords.length; i++) {
var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);
if (cIndex != null) {
colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
break;
}
}
}
var areaInterval = getInterval(splitAreaModel, labelInterval);
var prev = axis.toGlobalCoord(ticksCoords[0].coord);
var areaStyle = areaStyleModel.getAreaStyle();
areaColors = zrUtil.isArray(areaColors) ? areaColors : [areaColors];
var showMinLabel = axisModel.get('axisLabel.showMinLabel');
var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');
for (var i = 1; i < ticksCoords.length; i++) {
if (ifIgnoreOnTick(
axis, i, areaInterval, ticksCoords.length,
showMinLabel, showMaxLabel
) && (i < ticksCoords.length - 1)) {
continue;
}
var tickCoord = axis.toGlobalCoord(ticksCoords[i]);
var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
var x;
var y;
var width;
var height;
if (axis.isHorizontal()) {
x = prevX;
x = prev;
y = gridRect.y;
width = tickCoord - x;
height = gridRect.height;
prev = x + width;
}
else {
x = gridRect.x;
y = prevY;
y = prev;
width = gridRect.width;
height = tickCoord - y;
prev = y + height;
}
var colorIndex = (count++) % areaColors.length;
this._axisGroup.add(new graphic.Rect({
anid: 'area_' + ticks[i],
var tickValue = ticksCoords[i - 1].tickValue;
newSplitAreaColors.set(tickValue, colorIndex);
this._axisGroup.add(new graphic.Rect({
anid: 'area_' + tickValue,
shape: {
x: x,
y: y,
......@@ -225,9 +219,10 @@ var CartesianAxisView = AxisView.extend({
silent: true
}));
prevX = x + width;
prevY = y + height;
colorIndex = (colorIndex + 1) % areaColorsLen;
}
this._splitAreaColors = newSplitAreaColors;
}
});
......
......@@ -60,7 +60,7 @@ export default AxisView.extend({
shape: {
cx: polar.cx,
cy: polar.cy,
r: ticksCoords[i]
r: ticksCoords[i].coord
},
silent: true
}));
......@@ -83,6 +83,9 @@ export default AxisView.extend({
* @private
*/
_splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
if (!ticksCoords.length) {
return;
}
var splitAreaModel = radiusAxisModel.getModel('splitArea');
var areaStyleModel = splitAreaModel.getModel('areaStyle');
......@@ -93,7 +96,7 @@ export default AxisView.extend({
var splitAreas = [];
var prevRadius = ticksCoords[0];
var prevRadius = ticksCoords[0].coord;
for (var i = 1; i < ticksCoords.length; i++) {
var colorIndex = (lineCount++) % areaColors.length;
splitAreas[colorIndex] = splitAreas[colorIndex] || [];
......@@ -102,13 +105,13 @@ export default AxisView.extend({
cx: polar.cx,
cy: polar.cy,
r0: prevRadius,
r: ticksCoords[i],
r: ticksCoords[i].coord,
startAngle: 0,
endAngle: Math.PI * 2
},
silent: true
}));
prevRadius = ticksCoords[i];
prevRadius = ticksCoords[i].coord;
}
// Simple optimization
......
......@@ -2,12 +2,9 @@
import * as zrUtil from 'zrender/src/core/util';
import AxisBuilder from './AxisBuilder';
import * as graphic from '../../util/graphic';
import * as singleAxisHelper from './singleAxisHelper';
import * as singleAxisHelper from '../../coord/single/singleAxisHelper';
import AxisView from './AxisView';
var getInterval = AxisBuilder.getInterval;
var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick;
var axisBuilderAttrs = [
'axisLine', 'axisTickLabel', 'axisName'
];
......@@ -35,13 +32,13 @@ var SingleAxisView = AxisView.extend({
group.add(axisBuilder.getGroup());
if (axisModel.get(selfBuilderAttr + '.show')) {
this['_' + selfBuilderAttr](axisModel, layout.labelInterval);
this['_' + selfBuilderAttr](axisModel);
}
SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
},
_splitLine: function(axisModel, labelInterval) {
_splitLine: function(axisModel) {
var axis = axisModel.axis;
if (axis.scale.isBlank()) {
......@@ -52,7 +49,6 @@ var SingleAxisView = AxisView.extend({
var lineStyleModel = splitLineModel.getModel('lineStyle');
var lineWidth = lineStyleModel.get('width');
var lineColors = lineStyleModel.get('color');
var lineInterval = getInterval(splitLineModel, labelInterval);
lineColors = lineColors instanceof Array ? lineColors : [lineColors];
......@@ -62,22 +58,15 @@ var SingleAxisView = AxisView.extend({
var splitLines = [];
var lineCount = 0;
var ticksCoords = axis.getTicksCoords();
var ticksCoords = axis.getTicksCoords({
tickModel: splitLineModel
});
var p1 = [];
var p2 = [];
var showMinLabel = axisModel.get('axisLabel.showMinLabel');
var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');
for (var i = 0; i < ticksCoords.length; ++i) {
if (ifIgnoreOnTick(
axis, i, lineInterval, ticksCoords.length,
showMinLabel, showMaxLabel
)) {
continue;
}
var tickCoord = axis.toGlobalCoord(ticksCoords[i]);
var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
if (isHorizontal) {
p1[0] = tickCoord;
p1[1] = gridRect.y;
......
import * as graphic from '../../util/graphic';
import BaseAxisPointer from './BaseAxisPointer';
import * as viewHelper from './viewHelper';
import * as cartesianAxisHelper from '../axis/cartesianAxisHelper';
import * as cartesianAxisHelper from '../../coord/cartesian/cartesianAxisHelper';
import AxisView from '../axis/AxisView';
var CartesianAxisPointer = BaseAxisPointer.extend({
......
import * as graphic from '../../util/graphic';
import BaseAxisPointer from './BaseAxisPointer';
import * as viewHelper from './viewHelper';
import * as singleAxisHelper from '../axis/singleAxisHelper';
import * as singleAxisHelper from '../../coord/single/singleAxisHelper';
import AxisView from '../axis/AxisView';
var XY = ['x', 'y'];
......
......@@ -80,7 +80,7 @@ export default echarts.extendComponentView({
shape: {
cx: cx,
cy: cy,
r: ticksRadius[i]
r: ticksRadius[i].coord
}
}));
}
......@@ -90,8 +90,8 @@ export default echarts.extendComponentView({
shape: {
cx: cx,
cy: cy,
r0: ticksRadius[i],
r: ticksRadius[i + 1]
r0: ticksRadius[i].coord,
r: ticksRadius[i + 1].coord
}
}));
}
......@@ -106,7 +106,7 @@ export default echarts.extendComponentView({
? ticksCoords.length - 1
: Math.min(ticksCoords.length - 1, realSplitNumber);
return zrUtil.map(ticksCoords, function (tickCoord) {
return radar.coordToPoint(tickCoord, idx);
return radar.coordToPoint(tickCoord.coord, idx);
});
});
......
......@@ -287,9 +287,16 @@ export default TimelineView.extend({
var axisType = timelineModel.get('axisType');
var scale = axisHelper.createScaleByModel(timelineModel, axisType);
// Customize scale. The `tickValue` is `dataIndex`.
scale.getTicks = function () {
return data.mapArray(['value'], function (value) {
return value;
});
};
var dataExtent = data.getDataExtent('value');
scale.setExtent(dataExtent[0], dataExtent[1]);
this._customizeScale(scale, data);
scale.niceTicks();
var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType);
......@@ -298,19 +305,6 @@ export default TimelineView.extend({
return axis;
},
_customizeScale: function (scale, data) {
scale.getTicks = function () {
return data.mapArray(['value'], function (value) {
return value;
});
};
scale.getTicksLabels = function () {
return zrUtil.map(this.getTicks(), scale.getLabel, scale);
};
},
_createGroup: function (name) {
var newGroup = this['_' + name] = new graphic.Group();
this.group.add(newGroup);
......@@ -343,23 +337,24 @@ export default TimelineView.extend({
*/
_renderAxisTick: function (layoutInfo, group, axis, timelineModel) {
var data = timelineModel.getData();
// Show all ticks, despite ignoring strategy.
var ticks = axis.scale.getTicks();
each(ticks, function (value, dataIndex) {
// The value is dataIndex, see the costomized scale.
each(ticks, function (value) {
var tickCoord = axis.dataToCoord(value);
var itemModel = data.getItemModel(dataIndex);
var itemModel = data.getItemModel(value);
var itemStyleModel = itemModel.getModel('itemStyle');
var hoverStyleModel = itemModel.getModel('emphasis.itemStyle');
var symbolOpt = {
position: [tickCoord, 0],
onclick: bind(this._changeTimeline, this, dataIndex)
onclick: bind(this._changeTimeline, this, value)
};
var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt);
graphic.setHoverStyle(el, hoverStyleModel.getItemStyle());
if (itemModel.get('tooltip')) {
el.dataIndex = dataIndex;
el.dataIndex = value;
el.dataModel = timelineModel;
}
else {
......@@ -373,28 +368,23 @@ export default TimelineView.extend({
* @private
*/
_renderAxisLabel: function (layoutInfo, group, axis, timelineModel) {
var labelModel = timelineModel.getModel('label');
var labelModel = axis.getLabelModel();
if (!labelModel.get('show')) {
return;
}
var data = timelineModel.getData();
var ticks = axis.scale.getTicks();
var labels = axisHelper.getFormattedLabels(
axis, labelModel.get('formatter')
);
var labelInterval = axis.getLabelInterval();
var labels = axis.getViewLabels();
each(ticks, function (tick, dataIndex) {
if (axis.isLabelIgnored(dataIndex, labelInterval)) {
return;
}
each(labels, function (labelItem) {
// The tickValue is dataIndex, see the costomized scale.
var dataIndex = labelItem.tickValue;
var itemModel = data.getItemModel(dataIndex);
var normalLabelModel = itemModel.getModel('label');
var hoverLabelModel = itemModel.getModel('emphasis.label');
var tickCoord = axis.dataToCoord(tick);
var tickCoord = axis.dataToCoord(labelItem.tickValue);
var textEl = new graphic.Text({
position: [tickCoord, 0],
rotation: layoutInfo.labelRotation - layoutInfo.rotation,
......@@ -402,7 +392,7 @@ export default TimelineView.extend({
silent: false
});
graphic.setTextStyle(textEl.style, normalLabelModel, {
text: labels[dataIndex],
text: labelItem.formattedLabel,
textAlign: layoutInfo.labelAlign,
textVerticalAlign: layoutInfo.labelBaseline
});
......
import * as zrUtil from 'zrender/src/core/util';
import Axis from '../../coord/Axis';
import * as axisHelper from '../../coord/axisHelper';
/**
* Extend axis 2d
......@@ -26,12 +25,6 @@ var TimelineAxis = function (dim, scale, coordExtent, axisType) {
*/
this.type = axisType || 'value';
/**
* @private
* @type {number}
*/
this._autoLabelInterval;
/**
* Axis model
* @param {module:echarts/component/TimelineModel}
......@@ -44,47 +37,17 @@ TimelineAxis.prototype = {
constructor: TimelineAxis,
/**
* @public
* @return {number}
* @override
*/
getLabelInterval: function () {
var timelineModel = this.model;
var labelModel = timelineModel.getModel('label');
var labelInterval = labelModel.get('interval');
if (labelInterval != null && labelInterval != 'auto') {
return labelInterval;
}
var labelInterval = this._autoLabelInterval;
if (!labelInterval) {
labelInterval = this._autoLabelInterval = axisHelper.getAxisLabelInterval(
zrUtil.map(this.scale.getTicks(), this.dataToCoord, this),
axisHelper.getFormattedLabels(this, labelModel.get('formatter')),
labelModel.getFont(),
timelineModel.get('orient') === 'horizontal' ? 0 : 90,
labelModel.get('rotate')
);
}
return labelInterval;
getLabelModel: function () {
return this.model.getModel('label');
},
/**
* If label is ignored.
* Automatically used when axis is category and label can not be all shown
* @public
* @param {number} idx
* @return {boolean}
* @override
*/
isLabelIgnored: function (idx) {
if (this.type === 'category') {
var labelInterval = this.getLabelInterval();
return ((typeof labelInterval === 'function')
&& !labelInterval(idx, this.scale.getLabel(idx)))
|| idx % (labelInterval + 1);
}
isHorizontal: function () {
return this.model.get('orient') === 'horizontal';
}
};
......
import * as zrUtil from 'zrender/src/core/util';
import * as numberUtil from '../util/number';
import {each, map, createHashMap} from 'zrender/src/core/util';
import {linearMap, getPixelPrecision} from '../util/number';
import * as axisHelper from './axisHelper';
var linearMap = numberUtil.linearMap;
function fixExtentWithBands(extent, nTick) {
var size = extent[1] - extent[0];
var len = nTick;
var margin = size / len / 2;
extent[0] += margin;
extent[1] -= margin;
}
var NORMALIZED_EXTENT = [0, 1];
var normalizedExtent = [0, 1];
/**
* @name module:echarts/coord/CartesianAxis
* Base class of Axis.
* @constructor
*/
var Axis = function (dim, scale, extent) {
/**
* Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'
* Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'.
* @type {string}
*/
this.dim = dim;
......@@ -50,10 +40,12 @@ var Axis = function (dim, scale, extent) {
this.onBand = false;
/**
* Key: tickCategoryInterval
* Value: {ticks, labels}
* @private
* @type {number}
* @type {HashMap}
*/
this._labelInterval;
this._ticksCache = createHashMap();
};
Axis.prototype = {
......@@ -95,7 +87,7 @@ Axis.prototype = {
* @return {number}
*/
getPixelPrecision: function (dataExtent) {
return numberUtil.getPixelPrecision(
return getPixelPrecision(
dataExtent || this.scale.getExtent(),
this._extent
);
......@@ -128,7 +120,7 @@ Axis.prototype = {
fixExtentWithBands(extent, scale.count());
}
return linearMap(data, normalizedExtent, extent, clamp);
return linearMap(data, NORMALIZED_EXTENT, extent, clamp);
},
/**
......@@ -146,7 +138,7 @@ Axis.prototype = {
fixExtentWithBands(extent, scale.count());
}
var t = linearMap(coord, extent, normalizedExtent, clamp);
var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp);
return this.scale.scale(t);
},
......@@ -162,57 +154,58 @@ Axis.prototype = {
},
/**
* @return {Array.<number>}
* Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`,
* `axis.getTicksCoords` considers `onBand`, which is used by
* `boundaryGap:true` of category axis and splitLine and splitArea.
* @param {Object} [opt]
* @param {number} [opt.tickModel=axis.model.getModel('axisTick')]
* @param {boolean} [opt.clamp] If `false`, clip. If `true`, clamp.
* @return {Array.<Object>} [{
* coord: ...,
* tickValue: ...
* }, ...]
*/
getTicksCoords: function (alignWithLabel) {
if (this.onBand && !alignWithLabel) {
var bands = this.getBands();
var coords = [];
for (var i = 0; i < bands.length; i++) {
coords.push(bands[i][0]);
}
if (bands[i - 1]) {
coords.push(bands[i - 1][1]);
}
return coords;
}
else {
return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this);
}
getTicksCoords: function (opt) {
opt = opt || {};
var tickModel = opt.tickModel || this.model.getModel('axisTick');
var alignWithLabel = tickModel.get('alignWithLabel');
var tickCategoryInterval = tickModel.get('interval');
var result = axisHelper.createAxisTicksAndLabels(this, {
tickCategoryInterval: tickCategoryInterval
});
var ticks = result.ticks;
var ticksCoords = map(ticks, function (tickValue) {
return {
coord: this.dataToCoord(tickValue),
tickValue: tickValue
};
}, this);
fixOnBandTicksCoords(
this, ticksCoords, result.tickCategoryInterval, alignWithLabel, opt.clamp
);
return ticksCoords;
},
/**
* Coords of labels are on the ticks or on the middle of bands
* @return {Array.<number>}
* @return {Array.<Object>} [{
* formattedLabel: string,
* rawLabel: axis.scale.getLabel(tickValue)
* tickValue: number
* }, ...]
*/
getLabelsCoords: function () {
return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this);
getViewLabels: function () {
return axisHelper.createAxisTicksAndLabels(this, {
tickCategoryInterval: this.model.get('axisTick.interval')
}).labels;
},
/**
* Get bands.
*
* If axis has labels [1, 2, 3, 4]. Bands on the axis are
* |---1---|---2---|---3---|---4---|.
*
* @return {Array}
*/
// FIXME Situation when labels is on ticks
getBands: function () {
var extent = this.getExtent();
var bands = [];
var len = this.scale.count();
var start = extent[0];
var end = extent[1];
var span = end - start;
for (var i = 0; i < len; i++) {
bands.push([
span * i / len + start,
span * (i + 1) / len + start
]);
}
return bands;
getLabelModel: function () {
return this.model.getModel('axisLabel');
},
/**
......@@ -242,42 +235,64 @@ Axis.prototype = {
* @abstract
* @return {number} Get axis rotate, by degree.
*/
getRotate: null,
getRotate: null
/**
* Get interval of the axis label.
* To get precise result, at least one of `getRotate` and `isHorizontal`
* should be implemented.
* @return {number}
*/
getLabelInterval: function () {
var labelInterval = this._labelInterval;
if (!labelInterval) {
var axisModel = this.model;
var labelModel = axisModel.getModel('axisLabel');
labelInterval = labelModel.get('interval');
if (this.type === 'category'
&& (labelInterval == null || labelInterval === 'auto')
) {
labelInterval = axisHelper.getAxisLabelInterval(
zrUtil.map(this.scale.getTicks(), this.dataToCoord, this),
axisModel.getFormattedLabels(),
labelModel.getFont(),
this.getRotate
? this.getRotate()
: (this.isHorizontal && !this.isHorizontal())
? 90
: 0,
labelModel.get('rotate')
);
}
this._labelInterval = labelInterval;
};
function fixExtentWithBands(extent, nTick) {
var size = extent[1] - extent[0];
var len = nTick;
var margin = size / len / 2;
extent[0] += margin;
extent[1] -= margin;
}
// If axis has labels [1, 2, 3, 4]. Bands on the axis are
// |---1---|---2---|---3---|---4---|.
// So the displayed ticks and splitLine/splitArea should between
// each data item, otherwise cause misleading (e.g., split tow bars
// of a single data item when there are two bar series).
// Also consider if tickCategoryInterval > 0 and onBand, ticks and
// splitLine/spliteArea should layout appropriately corresponding
// to displayed labels. (So we should not use `getBandWidth` in this
// case).
function fixOnBandTicksCoords(axis, ticksCoords, tickCategoryInterval, alignWithLabel, clamp) {
var ticksLen = ticksCoords.length;
if (axis.onBand && !alignWithLabel && ticksLen) {
var axisExtent = axis.getExtent();
var last;
if (ticksLen === 1) {
ticksCoords[0].coord = axisExtent[0];
last = ticksCoords[1] = {coord: axisExtent[0]};
}
else {
var shift = (ticksCoords[1].coord - ticksCoords[0].coord);
each(ticksCoords, function (ticksItem) {
ticksItem.coord -= shift / 2;
var tickCategoryInterval = tickCategoryInterval || 0;
// Avoid split a single data item when odd interval.
if (tickCategoryInterval % 2 > 0) {
ticksItem.coord -= shift / ((tickCategoryInterval + 1) * 2);
}
});
last = {coord: ticksCoords[ticksLen - 1].coord + shift};
ticksCoords.push(last);
}
return labelInterval;
}
};
var inverse = axisExtent[0] > axisExtent[1];
if (inverse
? ticksCoords[0].coord > axisExtent[0]
: ticksCoords[0].coord < axisExtent[0]
) {
clamp ? (ticksCoords[0].coord = axisExtent[0]) : ticksCoords.shift();
}
if (inverse
? last.coord < axisExtent[1]
: last.coord > axisExtent[1]
) {
clamp ? (last.coord = axisExtent[1]) : ticksCoords.pop();
}
}
}
export default Axis;
\ No newline at end of file
export default Axis;
......@@ -6,10 +6,14 @@ import IntervalScale from '../scale/Interval';
import Scale from '../scale/Scale';
import * as numberUtil from '../util/number';
import {calBarWidthAndOffset} from '../layout/barGrid';
import {makeInner} from '../util/model';
import BoundingRect from 'zrender/src/core/BoundingRect';
import '../scale/Time';
import '../scale/Log';
var inner = makeInner();
/**
* Get axis scale extent before niced.
* Item of returned array can only be number (including Infinity and NaN).
......@@ -253,94 +257,413 @@ export function ifAxisCrossZero(axis) {
}
/**
* @param {Array.<number>} tickCoords In axis self coordinate.
* @param {Array.<string>} labels
* @param {string} font
* @param {number} axisRotate 0: towards right horizontally, clock-wise is negative.
* @param {number} [labelRotate=0] 0: towards right horizontally, clock-wise is negative.
* @param {module:echarts/coord/Axis} axis
* @return {Function} Label formatter function.
* param: {number} tickValue,
* param: {number} idx, the index in all ticks.
* If category axis, this param is not requied.
* return: {string} label string.
*/
function makeLabelFormatter(axis) {
var labelFormatter = axis.getLabelModel().get('formatter');
var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null;
if (typeof labelFormatter === 'string') {
labelFormatter = (function (tpl) {
return function (val) {
return tpl.replace('{value}', val != null ? val : '');
};
})(labelFormatter);
// Consider empty array
return labelFormatter;
}
else if (typeof labelFormatter === 'function') {
return function (tickValue, idx) {
// The original intention of `idx` is "the index of the tick in all ticks".
// But the previous implementation of category axis do not consider the
// `axisLabel.interval`, which cause that, for example, the `interval` is
// `1`, then the ticks "name5", "name7", "name9" are displayed, where the
// corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep
// the definition here for back compatibility.
if (categoryTickStart != null) {
idx = tickValue - categoryTickStart;
}
return labelFormatter(getAxisRawValue(axis, tickValue), idx);
};
}
else {
return function (tick) {
return axis.scale.getLabel(tick);
};
}
}
export function getAxisRawValue(axis, value) {
// In category axis with data zoom, tick is not the original
// index of axis.data. So tick should not be exposed to user
// in category axis.
return axis.type === 'category' ? axis.scale.getLabel(value) : value;
}
/**
* Performance sensible in the large category data case.
* @param {module:echats/coord/Axis} axis
* @param {Object} opt
* @param {number} [opt.tickCategoryInterval] Can be null/'auto'. Can also be
* axisTick.interval, splitLine.interval, splitArea.interval.
* @return {Object} {
* ticks: [number, ...]
* labels: [{
* formattedLabel: string,
* rawLabel: string,
* tickValue: number
* }, ...],
* labelCategoryInterval,
* tickCategoryInterval
* }
*/
export function createAxisTicksAndLabels(axis, opt) {
// Only ordinal scale support tick interval
return axis.type === 'category'
? createCategoryTicksAndLabels(axis, opt)
: createRealNumberTicksAndLabels(axis, opt);
}
function createCategoryTicksAndLabels(axis, opt) {
var labelModel = axis.getLabelModel();
// (1) Only add min max label here but leave overlap checking
// to render stage, which also ensure the returned list
// suitable for splitLine and splitArea rendering.
// (2) Scales except category always contain min max label so
// do not need to perform this process.
var showMinMax = {
min: labelModel.get('showMinLabel'),
max: labelModel.get('showMaxLabel')
};
// Large category data calculation is performence sensitive, and ticks and label
// probably be fetched by multiple times. So we cache the result.
// axis is created each time during a ec process, so we do not need to clear cache.
var ticksCache = getListCache(axis, 'ticks');
var labelsCache = getListCache(axis, 'labels');
var labelCategoryInterval = normalizeAuto(labelModel.get('interval'));
var labels = listCacheGet(labelsCache, labelCategoryInterval);
if (!labels) {
if (zrUtil.isFunction(labelCategoryInterval)) {
labels = makeLabelsByCustomizedCategoryInterval(axis, labelCategoryInterval);
}
else {
if (labelCategoryInterval === 'auto') {
labelCategoryInterval = calculateAutoCategoryInterval(axis);
}
labels = makeLabelsByNumericCategoryInterval(axis, labelCategoryInterval, showMinMax);
}
listCacheSet(labelsCache, labelCategoryInterval, labels);
}
var tickCategoryInterval = normalizeAuto(opt.tickCategoryInterval);
var ticks = listCacheGet(ticksCache, tickCategoryInterval);
if (!ticks) {
if (zrUtil.isFunction(tickCategoryInterval)) {
ticks = makeLabelsByCustomizedCategoryInterval(axis, tickCategoryInterval, true);
}
else if (tickCategoryInterval === 'auto' || tickCategoryInterval === labelCategoryInterval) {
// Always use label interval by default.
tickCategoryInterval = labelCategoryInterval;
ticks = zrUtil.map(labels, function (labelItem) {
return labelItem.tickValue;
});
}
else {
ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, showMinMax, true);
}
listCacheSet(ticksCache, tickCategoryInterval, ticks);
}
return {
ticks: ticks,
labels: labels,
labelCategoryInterval: labelCategoryInterval,
tickCategoryInterval: tickCategoryInterval
};
}
function createRealNumberTicksAndLabels(axis, opt) {
var ticks = axis.scale.getTicks();
var labelFormatter = makeLabelFormatter(axis);
var labels = zrUtil.map(ticks, function (tickValue, idx) {
return {
formattedLabel: labelFormatter(tickValue, idx),
rawLabel: axis.scale.getLabel(tickValue),
tickValue: tickValue
};
});
return {ticks: ticks, labels: labels};
}
function getListCache(axis, prop) {
// Because key can be funciton, and cache size always be small, we use array cache.
return inner(axis)[prop] || (inner(axis)[prop] = []);
}
function listCacheGet(cache, key) {
for (var i = 0; i < cache.length; i++) {
if (cache[i].key === key) {
return cache[i].value;
}
}
}
function listCacheSet(cache, key, value) {
cache.push({key: key, value: value});
}
/**
* Performance sensitive for large category data.
* Get interval of the axis label.
* To get precise result, at least one of `getRotate` and `isHorizontal`
* should be implemented.
* @param {module:echarts/coord/Axis} axis
* @return {number}
*/
export function getAxisLabelInterval(tickCoords, labels, font, axisRotate, labelRotate) {
var textSpaceTakenRect;
var autoLabelInterval = 0;
var accumulatedLabelInterval = 0;
var rotation = (axisRotate - labelRotate) / 180 * Math.PI;
function calculateAutoCategoryInterval(axis) {
var params = fetchAutoCategoryIntervalCalculationParams(axis);
var labelFormatter = makeLabelFormatter(axis);
var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI;
var ordinalScale = axis.scale;
var ordinalExtent = ordinalScale.getExtent();
// Providing this method is for optimization:
// avoid generating a long array by `getTicks`
// in large category data case.
var tickCount = ordinalScale.count();
var step = 1;
if (labels.length > 40) {
// Simple optimization for large amount of labels
step = Math.floor(labels.length / 40);
// Simple optimization. Empirical value: tick count less 40.
if (tickCount > 40) {
step = Math.max(1, Math.floor(tickCount / 40));
}
for (var i = 0; i < tickCoords.length; i += step) {
var tickCoord = tickCoords[i];
var textSpaceTakenRect;
var accumulatedLabelInterval = 0;
for (var tickValue = ordinalExtent[0]; tickValue <= ordinalExtent[1]; ) {
var formattedLabel = labelFormatter(tickValue);
// Not precise, do not consider align and vertical align
// and each distance from axis line yet.
var rect = textContain.getBoundingRect(
labels[i], font, 'center', 'top'
formattedLabel, params.font, 'center', 'top'
);
// Polar is also calculated in assumptive linear layout here.
var tickCoord = axis.dataToCoord(tickValue);
rect.x += tickCoord * Math.cos(rotation);
rect.y += tickCoord * Math.sin(rotation);
// Magic number
rect.width *= 1.3;
rect.height *= 1.3;
if (!textSpaceTakenRect) {
textSpaceTakenRect = rect.clone();
textSpaceTakenRect = rect;
tickValue += step;
}
// There is no space for current label;
// There is no space for current label.
else if (textSpaceTakenRect.intersect(rect)) {
accumulatedLabelInterval++;
autoLabelInterval = Math.max(autoLabelInterval, accumulatedLabelInterval);
tickValue++;
}
else {
textSpaceTakenRect.union(rect);
// Reset
accumulatedLabelInterval = 0;
if (accumulatedLabelInterval) {
// Optimize: add step to escape uncessary loop.
step += accumulatedLabelInterval;
accumulatedLabelInterval = 0;
}
tickValue += step;
}
}
if (autoLabelInterval === 0 && step > 1) {
return step;
if (accumulatedLabelInterval) {
step += accumulatedLabelInterval;
}
return (autoLabelInterval + 1) * step - 1;
var cache = inner(axis.model);
var lastStep = cache.lastStep;
var lastTickCount = cache.lastTickCount;
// Use cache to keep interval stable while moving zoom window,
// otherwise the calculated interval might jitter when the zoom
// window size is close to the interval-changing size.
if (lastStep != null
&& lastTickCount != null
&& Math.abs(lastStep - step) <= 1
&& Math.abs(lastTickCount - tickCount) <= 1
// Always choose the bigger one, otherwise the critical
// point is not the same when zooming in or zooming out.
&& lastStep > step
) {
step = lastStep;
}
// Only update cache if cache not used, otherwise the
// changing of interval is too insensitive.
else {
cache.lastTickCount = tickCount;
cache.lastStep = step;
}
return step - 1;
}
function fetchAutoCategoryIntervalCalculationParams(axis) {
var labelModel = axis.getLabelModel();
return {
axisRotate: axis.getRotate
? axis.getRotate()
: (axis.isHorizontal && !axis.isHorizontal())
? 90
: 0,
labelRotate: labelModel.get('rotate') || 0,
font: labelModel.getFont()
};
}
function makeLabelsByNumericCategoryInterval(axis, categoryInterval, showMinMax, onlyTick) {
var labelFormatter = makeLabelFormatter(axis);
var ordinalScale = axis.scale;
var ordinalExtent = ordinalScale.getExtent();
var result = [];
// TODO: axisType: ordinalTime, pick the tick from each month/day/year/...
var step = Math.max((categoryInterval || 0) + 1, 1);
var startTick = ordinalExtent[0];
var tickCount = ordinalScale.count();
// Calculate start tick based on zero if possible to keep label consistent
// while zooming and moving while interval > 0. Otherwise the selection
// of displayable ticks and symbols probably keep changing.
// 3 is empirical value.
if (startTick !== 0 && step > 1 && tickCount / step > 2) {
startTick = Math.round(Math.ceil(startTick / step) * step);
}
if (showMinMax.min && startTick !== ordinalExtent[0]) {
addItem(ordinalExtent[0]);
}
// Optimize: avoid generating large array by `ordinalScale.getTicks()`.
var tickValue = startTick;
for (; tickValue <= ordinalExtent[1]; tickValue += step) {
addItem(tickValue);
}
if (showMinMax.max && tickValue !== ordinalExtent[1]) {
addItem(ordinalExtent[1]);
}
function addItem(tVal) {
result.push(onlyTick
? tVal
: {
formattedLabel: labelFormatter(tVal),
rawLabel: ordinalScale.getLabel(tVal),
tickValue: tVal
}
);
}
return result;
}
// When interval is function, the result `false` means ignore the tick.
// It is time consuming for large category data.
function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) {
var ordinalScale = axis.scale;
var labelFormatter = makeLabelFormatter(axis);
var result = [];
zrUtil.each(ordinalScale.getTicks(), function (tickValue) {
var rawLabel = ordinalScale.getLabel(tickValue);
if (categoryInterval(tickValue, rawLabel)) {
result.push(onlyTick
? tickValue
: {
formattedLabel: labelFormatter(tickValue),
rawLabel: rawLabel,
tickValue: tickValue
}
);
}
});
return result;
}
// Can be null|'auto'
function normalizeAuto(setting) {
return setting == null ? 'auto' : setting;
}
/**
* @param {Object} axis
* @param {Function} labelFormatter
* @return {Array.<string>}
* @param {module:echarts/coord/Axis} axis
* @return {module:zrender/core/BoundingRect} Be null/undefined if no labels.
*/
export function getFormattedLabels(axis, labelFormatter) {
var scale = axis.scale;
var labels = scale.getTicksLabels();
var ticks = scale.getTicks();
if (typeof labelFormatter === 'string') {
labelFormatter = (function (tpl) {
return function (val) {
return tpl.replace('{value}', val != null ? val : '');
};
})(labelFormatter);
// Consider empty array
return zrUtil.map(labels, labelFormatter);
export function estimateLabelUnionRect(axis) {
var axisModel = axis.model;
if (!axisModel.get('axisLabel.show')) {
return;
}
else if (typeof labelFormatter === 'function') {
return zrUtil.map(ticks, function (tick, idx) {
return labelFormatter(
getAxisRawValue(axis, tick),
idx
);
}, this);
var scale = axis.scale;
var isCategory = axis.type === 'category';
var realNumberScaleTicks;
var tickCount;
var categoryScaleExtent = scale.getExtent();
// Optimize for large category data, avoid call `getTicks()`.
if (isCategory) {
tickCount = scale.count();
}
else {
return labels;
realNumberScaleTicks = scale.getTicks();
tickCount = realNumberScaleTicks.length;
}
var axisLabelModel = axis.getLabelModel();
var labelFormatter = makeLabelFormatter(axis);
var rect;
var step = 1;
// Simple optimization for large amount of labels
if (tickCount > 40) {
step = Math.ceil(tickCount / 40);
}
for (var i = 0; i < tickCount; i += step) {
var tickValue = realNumberScaleTicks ? realNumberScaleTicks[i] : categoryScaleExtent[0] + i;
var label = labelFormatter(tickValue);
var unrotatedSingleRect = axisLabelModel.getTextRect(label);
var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0);
rect ? rect.union(singleRect) : (rect = singleRect);
}
return rect;
}
export function getAxisRawValue(axis, value) {
// In category axis with data zoom, tick is not the original
// index of axis.data. So tick should not be exposed to user
// in category axis.
return axis.type === 'category' ? axis.scale.getLabel(value) : value;
function rotateTextRect(textRect, rotate) {
var rotateRadians = rotate * Math.PI / 180;
var boundingBox = textRect.plain();
var beforeWidth = boundingBox.width;
var beforeHeight = boundingBox.height;
var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
return rotatedRect;
}
......@@ -3,17 +3,6 @@ import * as axisHelper from './axisHelper';
export default {
/**
* Format labels
* @return {Array.<string>}
*/
getFormattedLabels: function () {
return axisHelper.getFormattedLabels(
this.axis,
this.get('axisLabel.formatter')
);
},
/**
* @param {boolean} origin
* @return {number|string} min value or 'dataMin' or null/undefined (means auto) or NaN
......
......@@ -81,21 +81,6 @@ Axis2D.prototype = {
this.grid.getOtherAxis();
},
/**
* If label is ignored.
* Automatically used when axis is category and label can not be all shown
* @param {number} idx
* @return {boolean}
*/
isLabelIgnored: function (idx) {
if (this.type === 'category') {
var labelInterval = this.getLabelInterval();
return ((typeof labelInterval === 'function')
&& !labelInterval(idx, this.scale.getLabel(idx)))
|| idx % (labelInterval + 1);
}
},
/**
* @override
*/
......
......@@ -5,10 +5,14 @@
*/
import {__DEV__} from '../../config';
import * as zrUtil from 'zrender/src/core/util';
import BoundingRect from 'zrender/src/core/BoundingRect';
import {isObject, each, map, indexOf, retrieve} from 'zrender/src/core/util';
import {getLayoutRect} from '../../util/layout';
import * as axisHelper from '../../coord/axisHelper';
import {
createScaleByModel,
ifAxisCrossZero,
niceScaleExtent,
estimateLabelUnionRect
} from '../../coord/axisHelper';
import Cartesian2D from './Cartesian2D';
import Axis2D from './Axis2D';
import CoordinateSystem from '../../CoordinateSystem';
......@@ -16,10 +20,6 @@ import CoordinateSystem from '../../CoordinateSystem';
// Depends on GridModel, AxisModel, which performs preprocess.
import './GridModel';
var each = zrUtil.each;
var ifAxisCrossZero = axisHelper.ifAxisCrossZero;
var niceScaleExtent = axisHelper.niceScaleExtent;
/**
* Check if the axis is used in the specified grid
* @inner
......@@ -28,40 +28,6 @@ function isAxisUsedInTheGrid(axisModel, gridModel, ecModel) {
return axisModel.getCoordSysModel() === gridModel;
}
function rotateTextRect(textRect, rotate) {
var rotateRadians = rotate * Math.PI / 180;
var boundingBox = textRect.plain();
var beforeWidth = boundingBox.width;
var beforeHeight = boundingBox.height;
var afterWidth = beforeWidth * Math.cos(rotateRadians) + beforeHeight * Math.sin(rotateRadians);
var afterHeight = beforeWidth * Math.sin(rotateRadians) + beforeHeight * Math.cos(rotateRadians);
var rotatedRect = new BoundingRect(boundingBox.x, boundingBox.y, afterWidth, afterHeight);
return rotatedRect;
}
function getLabelUnionRect(axis) {
var axisModel = axis.model;
var labels = axisModel.get('axisLabel.show') ? axisModel.getFormattedLabels() : [];
var axisLabelModel = axisModel.getModel('axisLabel');
var rect;
var step = 1;
var labelCount = labels.length;
if (labelCount > 40) {
// Simple optimization for large amount of labels
step = Math.ceil(labelCount / 40);
}
for (var i = 0; i < labelCount; i += step) {
if (!axis.isLabelIgnored(i)) {
var unrotatedSingleRect = axisLabelModel.getTextRect(labels[i]);
var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0);
rect ? rect.union(singleRect) : (rect = singleRect);
}
}
return rect;
}
function Grid(gridModel, ecModel, api) {
/**
* @type {Object.<string, module:echarts/coord/cartesian/Cartesian2D>}
......@@ -191,7 +157,7 @@ gridProto.resize = function (gridModel, api, ignoreContainLabel) {
if (!ignoreContainLabel && gridModel.get('containLabel')) {
each(axesList, function (axis) {
if (!axis.model.get('axisLabel.inside')) {
var labelUnionRect = getLabelUnionRect(axis);
var labelUnionRect = estimateLabelUnionRect(axis);
if (labelUnionRect) {
var dim = axis.isHorizontal() ? 'height' : 'width';
var margin = axis.model.get('axisLabel.margin');
......@@ -262,7 +228,7 @@ gridProto.getCartesian = function (xAxisIndex, yAxisIndex) {
return this._coordsMap[key];
}
if (zrUtil.isObject(xAxisIndex)) {
if (isObject(xAxisIndex)) {
yAxisIndex = xAxisIndex.yAxisIndex;
xAxisIndex = xAxisIndex.xAxisIndex;
}
......@@ -324,7 +290,7 @@ gridProto._findConvertTarget = function (ecModel, finder) {
if (seriesModel) {
cartesian = seriesModel.coordinateSystem;
zrUtil.indexOf(coordsList, cartesian) < 0 && (cartesian = null);
indexOf(coordsList, cartesian) < 0 && (cartesian = null);
}
else if (xAxisModel && yAxisModel) {
cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
......@@ -438,7 +404,7 @@ gridProto._initCartesian = function (gridModel, ecModel, api) {
axisPositionUsed[axisPosition] = true;
var axis = new Axis2D(
axisType, axisHelper.createScaleByModel(axisModel),
axisType, createScaleByModel(axisModel),
[0, 0],
axisModel.get('type'),
axisPosition
......@@ -475,7 +441,7 @@ gridProto._initCartesian = function (gridModel, ecModel, api) {
*/
gridProto._updateScale = function (ecModel, gridModel) {
// Reset scale
zrUtil.each(this._axesList, function (axis) {
each(this._axesList, function (axis) {
axis.scale.setExtent(Infinity, -Infinity);
});
ecModel.eachSeries(function (seriesModel) {
......@@ -523,8 +489,8 @@ gridProto.getTooltipAxes = function (dim) {
var baseAxis = (dim != null && dim !== 'auto')
? cartesian.getAxis(dim) : cartesian.getBaseAxis();
var otherAxis = cartesian.getOtherAxis(baseAxis);
zrUtil.indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
zrUtil.indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
});
return {baseAxes: baseAxes, otherAxes: otherAxes};
......@@ -559,12 +525,12 @@ var axesTypes = ['xAxis', 'yAxis'];
* @inner
*/
function findAxesModels(seriesModel, ecModel) {
return zrUtil.map(axesTypes, function (axisType) {
return map(axesTypes, function (axisType) {
var axisModel = seriesModel.getReferringComponents(axisType)[0];
if (__DEV__) {
if (!axisModel) {
throw new Error(axisType + ' "' + zrUtil.retrieve(
throw new Error(axisType + ' "' + retrieve(
seriesModel.get(axisType + 'Index'),
seriesModel.get(axisType + 'Id'),
0
......@@ -611,7 +577,7 @@ Grid.create = function (ecModel, api) {
if (__DEV__) {
if (!gridModel) {
throw new Error(
'Grid "' + zrUtil.retrieve(
'Grid "' + retrieve(
xAxisModel.get('gridIndex'),
xAxisModel.get('gridId'),
0
......
import * as zrUtil from 'zrender/src/core/util';
/**
* Can only be called after coordinate system creation stage.
* (Can be called before coordinate system update stage).
*
* @param {Object} opt {labelInside}
* @return {Object} {
* position, rotation, labelDirection, labelOffset,
* tickDirection, labelRotate, labelInterval, z2
* tickDirection, labelRotate, z2
* }
*/
export function layout(gridModel, axisModel, opt) {
......@@ -58,9 +61,6 @@ export function layout(gridModel, axisModel, opt) {
var labelRotate = axisModel.get('axisLabel.rotate');
layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate;
// label interval when auto mode.
layout.labelInterval = axis.getLabelInterval();
// Over splitLine and splitArea
layout.z2 = 1;
......
......@@ -302,8 +302,7 @@ Parallel.prototype = {
axisLabelShow: posInfo.axisLabelShow,
nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth,
tickDirection: 1,
labelDirection: 1,
labelInterval: axes.get(dim).getLabelInterval()
labelDirection: 1
};
}, this);
},
......
......@@ -42,11 +42,6 @@ var SingleAxis = function (dim, scale, coordExtent, axisType, position) {
*/
this.orient = null;
/**
* @type {number}
*/
this._labelInterval = null;
};
SingleAxis.prototype = {
......
......@@ -4,10 +4,10 @@ import * as zrUtil from 'zrender/src/core/util';
* @param {Object} opt {labelInside}
* @return {Object} {
* position, rotation, labelDirection, labelOffset,
* tickDirection, labelRotate, labelInterval, z2
* tickDirection, labelRotate, z2
* }
*/
export function layout (axisModel, opt) {
export function layout(axisModel, opt) {
opt = opt || {};
var single = axisModel.coordinateSystem;
var axis = axisModel.axis;
......@@ -54,8 +54,6 @@ export function layout (axisModel, opt) {
labelRotation == null && (labelRotation = axisModel.get('axisLabel.rotate'));
layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation;
layout.labelInterval = axis.getLabelInterval();
layout.z2 = 1;
return layout;
......
......@@ -23,11 +23,12 @@ export default function (seriesType) {
}).slice(0, 2);
var dimLen = dims.length;
var stackResultDim = data.getCalculationInfo('stackResultDimension');
if (isDimensionStacked(data, dims[0], dims[1])) {
dims[0] = data.getCalculationInfo('stackResultDimension');
dims[0] = stackResultDim;
}
if (isDimensionStacked(data, dims[1], dims[0])) {
dims[1] = data.getCalculationInfo('stackResultDimension');
dims[1] = stackResultDim;
}
function progress(params, data) {
......
......@@ -70,18 +70,6 @@ var IntervalScale = Scale.extend({
);
},
/**
* @return {Array.<string>}
*/
getTicksLabels: function () {
var labels = [];
var ticks = this.getTicks();
for (var i = 0; i < ticks.length; i++) {
labels.push(this.getLabel(ticks[i]));
}
return labels;
},
/**
* @param {number} data
* @param {Object} [opt]
......
......@@ -117,18 +117,6 @@ Scale.prototype.setExtent = function (start, end) {
}
};
/**
* @return {Array.<string>}
*/
Scale.prototype.getTicksLabels = function () {
var labels = [];
var ticks = this.getTicks();
for (var i = 0; i < ticks.length; i++) {
labels.push(this.getLabel(ticks[i]));
}
return labels;
};
/**
* When axis extent depends on data and no data exists,
* axis ticks should not be drawn, which is named 'blank'.
......@@ -145,6 +133,13 @@ Scale.prototype.setBlank = function (isBlank) {
this._isBlank = isBlank;
};
/**
* @abstract
* @param {*} tick
* @return {string} label of the tick.
*/
Scale.prototype.getLabel = null;
clazzUtil.enableClassExtend(Scale);
clazzUtil.enableClassManagement(Scale, {
......
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8">
<script src="lib/esl.js"></script>
<script src="lib/config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/facePrint.js"></script>
<script src="lib/testHelper.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="lib/reset.css">
</head>
<body>
<style>
.test-title {
background: #b8d4ff;
color: #000;
}
</style>
<div class="chart" id="main0"></div>
<div class="chart" id="main1"></div>
<script>
require([
'echarts'
], function (echarts) {
var xAxisData = [];
var data1 = [];
var data3 = [];
for (var i = 0; i < 100; i++) {
xAxisData.push('category' + i);
data1.push((Math.random() * 5).toFixed(2) * 1e6);
data3.push((Math.random() + 0.5).toFixed(2) * 1e6);
}
var option = {
backgroundColor: '#fe9',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
id: 'xx',
data: xAxisData,
axisTick: {
interval: 4,
alignWithLabel: true
},
axisLabel: {
},
splitArea: {
show: true
}
},
yAxis: {
id: 'yy',
axisTick: {
show: false
},
splitArea: {
show: false
}
},
grid: {
left: 0,
top: 0,
bottom: 0,
right: 0,
containLabel: true
},
dataZoom: [{
type: 'inside',
startValue: 17,
endValue: 24
}],
series: [{
name: 'bar',
type: 'bar',
stack: 'one',
cursor: 'move',
data: data1
}, {
name: 'bar3',
type: 'bar',
stack: 'two',
data: data3
}]
};
var chart = testHelper.create(echarts, 'main0', {
title: [
'Check containLabel'
],
option: option,
info: {grid: option.grid},
});
var rotate = 0;
chart && next();
function next() {
var nextInterval = rotate % 90 === 0 ? 2000: 70;
rotate = (rotate + 1) % 90;
setTimeout(function () {
chart.setOption({
xAxis: {
id: 'xx',
axisLabel: {
rotate: rotate
}
},
yAxis: {
id: 'yy',
axisLabel: {
rotate: rotate
}
}
});
next();
}, nextInterval);
}
});
</script>
<script>
require([
'echarts'
], function (echarts) {
var xAxisData = [];
var data1 = [];
var data3 = [];
for (var i = 0; i < 100; i++) {
xAxisData.push('category' + i);
data1.push((Math.random() * 5).toFixed(2) * 1e6);
data3.push((Math.random() + 0.5).toFixed(2) * 1e6);
}
var option = {
backgroundColor: '#fe9',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: [{
id: 'x0',
data: xAxisData,
axisTick: {
interval: 4,
alignWithLabel: true
},
axisLabel: {
},
splitArea: {
show: true
}
}, {
id: 'x1',
data: xAxisData,
axisTick: {
interval: 4,
alignWithLabel: true
},
axisLabel: {
},
splitArea: {
show: true
}
}],
yAxis: [{
id: 'y0',
axisTick: {
show: false
},
splitArea: {
show: false
}
}, {
id: 'y1',
axisTick: {
show: false
},
splitArea: {
show: false
}
}],
grid: {
left: 0,
top: 0,
bottom: 0,
right: 0,
containLabel: true
},
dataZoom: [{
type: 'inside',
startValue: 17,
endValue: 24
}],
series: [{
name: 'bar',
type: 'bar',
stack: 'one',
cursor: 'move',
data: data1
}, {
name: 'bar3',
xAxisIndex: 1,
yAxisIndex: 1,
type: 'bar',
stack: 'two',
data: data3
}]
};
var chart = testHelper.create(echarts, 'main1', {
title: [
'Check containLabel'
],
option: option,
info: {grid: option.grid},
});
var rotate = 0;
chart && next();
function next() {
var nextInterval = rotate % 90 === 0 ? 2000: 70;
rotate = (rotate + 1) % 90;
setTimeout(function () {
chart.setOption({
xAxis: [
{id: 'x0', axisLabel: {rotate: rotate}},
{id: 'x1', axisLabel: {rotate: rotate}}
],
yAxis: [
{id: 'y0', axisLabel: {rotate: rotate}},
{id: 'y1', axisLabel: {rotate: rotate}}
]
});
next();
}, nextInterval);
}
});
</script>
</body>
</html>
\ No newline at end of file
......@@ -38,22 +38,6 @@
require([
'echarts'
// 'echarts/chart/line',
// 'echarts/chart/bar',
// 'echarts/chart/pie',
// 'echarts/chart/scatter',
// 'echarts/chart/map',
// 'echarts/chart/parallel',
// 'echarts/chart/radar',
// 'echarts/component/grid',
// 'echarts/component/polar',
// 'echarts/component/geo',
// 'echarts/component/singleAxis',
// 'echarts/component/legend',
// 'echarts/component/tooltip',
// 'echarts/component/toolbox',
// 'echarts/component/visualMap',
// 'echarts/component/dataZoom'
], function (echarts) {
option = {
......
此差异已折叠。
......@@ -4,6 +4,7 @@
<script src="lib/esl.js"></script>
<script src="lib/config.js"></script>
<script src="lib/facePrint.js"></script>
<script src="lib/testHelper.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="lib/reset.css" />
</head>
......@@ -18,19 +19,14 @@
font-size: 14px;
margin: 0;
}
.chart {
height: 350px;
}
</style>
<h1>xAxis: {showMinLabel: null, showMaxLabel: null (auto)}. The last x label should not be displayed (overlap).</h1>
<div class="chart" id="chart-1"></div>
<h1>xAxis: {showMinLabel: null, showMaxLabel: null (auto)}. The last x label shoule be displayed (not overlap).</h1>
<div class="chart" id="chart0"></div>
<h1>xAxis: {showMinLabel: true, showMaxLabel: true}, yAxis: {showMaxLabel: false}. The last x label should be displayed. 100 on y should not be displayed.</h1>
<div class="chart" id="chart-1"></div>
<div class="chart" id="chart0"></div>
<div class="chart" id="chart1"></div>
<div class="chart" id="chart2"></div>
......@@ -46,26 +42,12 @@
require([
'data/rainfall.json',
'echarts'
// 'echarts/chart/line',
// 'echarts/component/legend',
// 'echarts/component/grid',
// 'echarts/component/tooltip',
// 'echarts/component/title',
// 'echarts/component/dataZoom',
// 'echarts/scale/Time'
], function (rainfallData, echarts) {
var chart = echarts.init(document.getElementById('chart-1'), null, {
});
chart.setOption({
var option = {
tooltip : {
trigger: 'axis'
},
grid: {
bottom: 150
},
dataZoom: {
show: true,
realtime: true,
......@@ -99,6 +81,15 @@
})
}
]
};
var chart = testHelper.create(echarts, 'chart-1', {
title: [
'The last x label should not be displayed (overlap).'
],
option: option,
info: option.xAxis,
infoKey: 'xAxis'
});
})
......@@ -116,20 +107,13 @@
require([
'data/rainfall.json',
'echarts'
// 'echarts/chart/line',
// 'echarts/component/legend',
// 'echarts/component/grid',
// 'echarts/component/tooltip',
// 'echarts/component/title',
// 'echarts/component/dataZoom',
// 'echarts/scale/Time'
], function (rainfallData, echarts) {
var chart = echarts.init(document.getElementById('chart0'), null, {
});
chart.setOption({
var option = {
tooltip : {
trigger: 'axis'
},
......@@ -170,6 +154,15 @@
})
}
]
};
var chart = testHelper.create(echarts, 'chart0', {
title: [
'The last x label shoule be displayed (not overlap).'
],
option: option,
info: option.xAxis,
infoKey: 'xAxis'
});
})
......@@ -188,26 +181,16 @@
require([
'data/rainfall.json',
'echarts'
// 'echarts/chart/line',
// 'echarts/component/legend',
// 'echarts/component/grid',
// 'echarts/component/tooltip',
// 'echarts/component/title',
// 'echarts/component/dataZoom',
// 'echarts/scale/Time'
], function (rainfallData, echarts) {
var chart = echarts.init(document.getElementById('chart1'), null, {
});
chart.setOption({
var option = {
tooltip : {
trigger: 'axis'
},
grid: {
bottom: 150
},
dataZoom: {
show: true,
realtime: true,
......@@ -249,6 +232,17 @@
})
}
]
};
var chart = testHelper.create(echarts, 'chart1', {
title: [
'The last x label should be displayed. The top tick on y should not be displayed.'
],
option: option,
info: {
yAxis: option.yAxis,
xAxis: option.xAxis
}
});
})
......@@ -259,5 +253,89 @@
<script>
require([
'data/rainfall.json',
'echarts'
], function (rainfallData, echarts) {
var chart = echarts.init(document.getElementById('chart1'), null, {
});
var option = {
tooltip: {
trigger: 'axis'
},
dataZoom: {
show: true,
realtime: true,
startValue: '2009-09-20 12:00',
end: 100
},
xAxis: {
axisTick: {
alignWithLabel: true
},
axisLabel: {
showMaxLabel: true,
showMinLabel: true,
formatter: function (value) {
return echarts.format.formatTime('yyyy-MM-dd hh:mm:ss', value);
}
},
data: rainfallData.flow.map(function (val, idx) {
return rainfallData.category[idx];
})
},
yAxis: {
name: '流量(m^3/s)',
axisLabel: {
inside: true,
showMaxLabel: false,
formatter: '{value}\n'
}
},
series: [
{
name: '流量',
type: 'line',
symbol: 'none',
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: rainfallData.flow.map(function (val, idx) {
return val;
})
}
]
};
var chart = testHelper.create(echarts, 'chart2', {
title: [
'category xAxis:The min and max x label should be displayed.'
],
option: option,
info: {
axisLabel: option.xAxis.axisLabel,
axisTick: option.xAxis.axisTick
},
infoKey: 'xAxis'
});
})
</script>
</body>
</html>
\ No newline at end of file
......@@ -174,6 +174,9 @@
// },
axisLine: {
onZero: true
// lineStyle: {
// width: 5
// }
},
splitLine: {
show: true
......@@ -187,6 +190,11 @@
// axisLabel: {
// show: false
// },
// axisLine: {
// lineStyle: {
// width: 5
// }
// },
axisTick: {
show: false
},
......
......@@ -49,8 +49,6 @@
xAxisData.push('类目' + i);
}
if (i < 5 && i > 1) {
data1.push(0);
}
......@@ -80,25 +78,27 @@
};
chart.setOption({
title: {
text: '折线图{a|asdf}Step line',
subtext: 'subtitle',
backgroundColor: '#ee99aa',
borderRadius: 5,
padding: 10,
textStyle: {
rich: {
a: {
color: '#338844',
fontSize: 30,
borderColor: '#119955',
borderWidth: 3,
backgroundColor: '#445566'
}
}
}
text: 'tick 14 and 20 should be red (has textStyle)'
},
// title: {
// text: '折线图{a|asdf}Step line',
// subtext: 'subtitle',
// backgroundColor: '#ee99aa',
// borderRadius: 5,
// padding: 10,
// textStyle: {
// rich: {
// a: {
// color: '#338844',
// fontSize: 30,
// borderColor: '#119955',
// borderWidth: 3,
// backgroundColor: '#445566'
// }
// }
// }
// },
legend: {
data: ['line', 'line2', 'line3']
......@@ -122,8 +122,8 @@
show: false
},
axisLabel: {
showMaxLabel: true,
showMinLabel: true
// showMaxLabel: true,
// showMinLabel: true
}
},
grid: {
......@@ -140,11 +140,17 @@
show: true
}
},
dataZoom: {
dataZoom: [{
type: 'inside',
start: 10,
end: 30
},
// start: 10,
// end: 30
startValue: 11,
endValue: 85
}, {
type: 'slider',
startValue: 11,
endValue: 85
}],
// animation: false,
series: [null, // 用于测试 option 中含有null的情况。
{
......
......@@ -32,14 +32,9 @@
require([
'echarts'
// 'zrender/core/util',
// 'echarts/chart/bar',
// 'echarts/component/legend',
// 'echarts/component/grid',
// 'echarts/component/tooltip',
// 'echarts/component/timeline'
], function (echarts) {
var zrUtil = echarts.util;
makeChart({
timeline: {
label: {
......@@ -63,7 +58,8 @@
symbolRotate: 30
}
});
makeChart({timeline: {inverse: true, controlStyle: {position: 'right'}}});
makeChart({timeline: {inverse: true, controlStyle: {position: 'right'}}, width: 400});
makeChart({timeline: {orient: 'vertical', x: 0, y: 10, width: 55, height: '80%'}});
makeChart({timeline: {orient: 'vertical', inverse: true, rewind: true, x: 0, y: 10, width: 55, height: '80%'}});
......@@ -118,7 +114,11 @@
var containerEl = document.getElementById('main');
var el = document.createElement('div');
el.className = 'block';
el.innerHTML = '<div class="ec"></div><label>'
var widthString = '';
if (opt.width != null) {
widthString = ' style="width:' + opt.width + 'px" ';
}
el.innerHTML = '<div class="ec" ' + widthString + '></div><label>'
+ encodeHTML(JSON.stringify(opt)) + '</label>';
containerEl.appendChild(el);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册