217 lines
7.8 KiB
Plaintext
217 lines
7.8 KiB
Plaintext
define(function(require) {
|
|
|
|
'use strict';
|
|
|
|
var zrUtil = require('zrender/core/util');
|
|
var numberUtil = require('../util/number');
|
|
var parsePercent = numberUtil.parsePercent;
|
|
|
|
function getSeriesStackId(seriesModel) {
|
|
return seriesModel.get('stack') || '__ec_stack_' + seriesModel.seriesIndex;
|
|
}
|
|
|
|
function calBarWidthAndOffset(barSeries, api) {
|
|
// Columns info on each category axis. Key is cartesian name
|
|
var columnsMap = {};
|
|
|
|
zrUtil.each(barSeries, function (seriesModel, idx) {
|
|
var cartesian = seriesModel.coordinateSystem;
|
|
|
|
var baseAxis = cartesian.getBaseAxis();
|
|
|
|
var columnsOnAxis = columnsMap[baseAxis.index] || {
|
|
remainedWidth: baseAxis.getBandWidth(),
|
|
autoWidthCount: 0,
|
|
categoryGap: '20%',
|
|
gap: '30%',
|
|
axis: baseAxis,
|
|
stacks: {}
|
|
};
|
|
var stacks = columnsOnAxis.stacks;
|
|
columnsMap[baseAxis.index] = columnsOnAxis;
|
|
|
|
var stackId = getSeriesStackId(seriesModel);
|
|
|
|
if (!stacks[stackId]) {
|
|
columnsOnAxis.autoWidthCount++;
|
|
}
|
|
stacks[stackId] = stacks[stackId] || {
|
|
width: 0,
|
|
maxWidth: 0
|
|
};
|
|
|
|
var barWidth = seriesModel.get('barWidth');
|
|
var barMaxWidth = seriesModel.get('barMaxWidth');
|
|
var barGap = seriesModel.get('barGap');
|
|
var barCategoryGap = seriesModel.get('barCategoryGap');
|
|
// TODO
|
|
if (barWidth && ! stacks[stackId].width) {
|
|
barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
|
|
stacks[stackId].width = barWidth;
|
|
columnsOnAxis.remainedWidth -= barWidth;
|
|
}
|
|
|
|
barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
|
|
(barGap != null) && (columnsOnAxis.gap = barGap);
|
|
(barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap);
|
|
});
|
|
|
|
var result = {};
|
|
|
|
zrUtil.each(columnsMap, function (columnsOnAxis, coordSysName) {
|
|
|
|
result[coordSysName] = {};
|
|
|
|
var stacks = columnsOnAxis.stacks;
|
|
var baseAxis = columnsOnAxis.axis;
|
|
var bandWidth = baseAxis.getBandWidth();
|
|
var categoryGap = parsePercent(columnsOnAxis.categoryGap, bandWidth);
|
|
var barGapPercent = parsePercent(columnsOnAxis.gap, 1);
|
|
|
|
var remainedWidth = columnsOnAxis.remainedWidth;
|
|
var autoWidthCount = columnsOnAxis.autoWidthCount;
|
|
var autoWidth = (remainedWidth - categoryGap)
|
|
/ (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
|
|
autoWidth = Math.max(autoWidth, 0);
|
|
|
|
// Find if any auto calculated bar exceeded maxBarWidth
|
|
zrUtil.each(stacks, function (column, stack) {
|
|
var maxWidth = column.maxWidth;
|
|
if (!column.width && maxWidth && maxWidth < autoWidth) {
|
|
maxWidth = Math.min(maxWidth, remainedWidth);
|
|
remainedWidth -= maxWidth;
|
|
column.width = maxWidth;
|
|
autoWidthCount--;
|
|
}
|
|
});
|
|
|
|
// Recalculate width again
|
|
autoWidth = (remainedWidth - categoryGap)
|
|
/ (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
|
|
autoWidth = Math.max(autoWidth, 0);
|
|
|
|
var widthSum = 0;
|
|
var lastColumn;
|
|
zrUtil.each(stacks, function (column, idx) {
|
|
if (!column.width) {
|
|
column.width = autoWidth;
|
|
}
|
|
lastColumn = column;
|
|
widthSum += column.width * (1 + barGapPercent);
|
|
});
|
|
if (lastColumn) {
|
|
widthSum -= lastColumn.width * barGapPercent;
|
|
}
|
|
|
|
var offset = -widthSum / 2;
|
|
zrUtil.each(stacks, function (column, stackId) {
|
|
result[coordSysName][stackId] = result[coordSysName][stackId] || {
|
|
offset: offset,
|
|
width: column.width
|
|
};
|
|
|
|
offset += column.width * (1 + barGapPercent);
|
|
});
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @param {string} seriesType
|
|
* @param {module:echarts/model/Global} ecModel
|
|
* @param {module:echarts/ExtensionAPI} api
|
|
*/
|
|
function barLayoutGrid(seriesType, ecModel, api) {
|
|
|
|
var barWidthAndOffset = calBarWidthAndOffset(
|
|
zrUtil.filter(
|
|
ecModel.getSeriesByType(seriesType),
|
|
function (seriesModel) {
|
|
return !ecModel.isSeriesFiltered(seriesModel)
|
|
&& seriesModel.coordinateSystem
|
|
&& seriesModel.coordinateSystem.type === 'cartesian2d';
|
|
}
|
|
)
|
|
);
|
|
|
|
var lastStackCoords = {};
|
|
|
|
ecModel.eachSeriesByType(seriesType, function (seriesModel) {
|
|
|
|
var data = seriesModel.getData();
|
|
var cartesian = seriesModel.coordinateSystem;
|
|
var baseAxis = cartesian.getBaseAxis();
|
|
|
|
var stackId = getSeriesStackId(seriesModel);
|
|
var columnLayoutInfo = barWidthAndOffset[baseAxis.index][stackId];
|
|
var columnOffset = columnLayoutInfo.offset;
|
|
var columnWidth = columnLayoutInfo.width;
|
|
var valueAxis = cartesian.getOtherAxis(baseAxis);
|
|
|
|
var barMinHeight = seriesModel.get('barMinHeight') || 0;
|
|
|
|
var valueAxisStart = baseAxis.onZero
|
|
? valueAxis.toGlobalCoord(valueAxis.dataToCoord(0))
|
|
: valueAxis.getGlobalExtent()[0];
|
|
|
|
var coords = cartesian.dataToPoints(data, true);
|
|
lastStackCoords[stackId] = lastStackCoords[stackId] || [];
|
|
|
|
data.setLayout({
|
|
offset: columnOffset,
|
|
size: columnWidth
|
|
});
|
|
data.each(valueAxis.dim, function (value, idx) {
|
|
// 空数据
|
|
if (isNaN(value)) {
|
|
return;
|
|
}
|
|
if (!lastStackCoords[stackId][idx]) {
|
|
lastStackCoords[stackId][idx] = {
|
|
// Positive stack
|
|
p: valueAxisStart,
|
|
// Negative stack
|
|
n: valueAxisStart
|
|
};
|
|
}
|
|
var sign = value >= 0 ? 'p' : 'n';
|
|
var coord = coords[idx];
|
|
var lastCoord = lastStackCoords[stackId][idx][sign];
|
|
var x, y, width, height;
|
|
if (valueAxis.isHorizontal()) {
|
|
x = lastCoord;
|
|
y = coord[1] + columnOffset;
|
|
width = coord[0] - lastCoord;
|
|
height = columnWidth;
|
|
|
|
if (Math.abs(width) < barMinHeight) {
|
|
width = (width < 0 ? -1 : 1) * barMinHeight;
|
|
}
|
|
lastStackCoords[stackId][idx][sign] += width;
|
|
}
|
|
else {
|
|
x = coord[0] + columnOffset;
|
|
y = lastCoord;
|
|
width = columnWidth;
|
|
height = coord[1] - lastCoord;
|
|
if (Math.abs(height) < barMinHeight) {
|
|
// Include zero to has a positive bar
|
|
height = (height <= 0 ? -1 : 1) * barMinHeight;
|
|
}
|
|
lastStackCoords[stackId][idx][sign] += height;
|
|
}
|
|
|
|
data.setItemLayout(idx, {
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height
|
|
});
|
|
}, true);
|
|
|
|
}, this);
|
|
}
|
|
|
|
return barLayoutGrid;
|
|
}); |