cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
384 lines (383 loc) • 14.2 kB
JavaScript
import { each, defaults, keys } from "../../../zrender/lib/core/util.mjs";
import { parsePercent } from "../util/number.mjs";
import { isDimensionStacked } from "../data/helper/dataStackHelper.mjs";
import createRenderPlanner from "../chart/helper/createRenderPlanner.mjs";
import { createFloat32Array } from "../util/vendor.mjs";
var STACK_PREFIX = "__ec_stack_";
function getSeriesStackId(seriesModel) {
return seriesModel.get("stack") || STACK_PREFIX + seriesModel.seriesIndex;
}
function getAxisKey(axis) {
return axis.dim + axis.index;
}
function getLayoutOnAxis(opt) {
var params = [];
var baseAxis = opt.axis;
var axisKey = "axis0";
if (baseAxis.type !== "category") {
return;
}
var bandWidth = baseAxis.getBandWidth();
for (var i = 0; i < opt.count || 0; i++) {
params.push(defaults({
bandWidth,
axisKey,
stackId: STACK_PREFIX + i
}, opt));
}
var widthAndOffsets = doCalBarWidthAndOffset(params);
var result = [];
for (var i = 0; i < opt.count; i++) {
var item = widthAndOffsets[axisKey][STACK_PREFIX + i];
item.offsetCenter = item.offset + item.width / 2;
result.push(item);
}
return result;
}
function prepareLayoutBarSeries(seriesType, ecModel) {
var seriesModels = [];
ecModel.eachSeriesByType(seriesType, function(seriesModel) {
if (isOnCartesian(seriesModel)) {
seriesModels.push(seriesModel);
}
});
return seriesModels;
}
function getValueAxesMinGaps(barSeries) {
var axisValues = {};
each(barSeries, function(seriesModel) {
var cartesian = seriesModel.coordinateSystem;
var baseAxis = cartesian.getBaseAxis();
if (baseAxis.type !== "time" && baseAxis.type !== "value") {
return;
}
var data = seriesModel.getData();
var key2 = baseAxis.dim + "_" + baseAxis.index;
var dimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim));
var store = data.getStore();
for (var i = 0, cnt = store.count(); i < cnt; ++i) {
var value = store.get(dimIdx, i);
if (!axisValues[key2]) {
axisValues[key2] = [value];
} else {
axisValues[key2].push(value);
}
}
});
var axisMinGaps = {};
for (var key in axisValues) {
if (axisValues.hasOwnProperty(key)) {
var valuesInAxis = axisValues[key];
if (valuesInAxis) {
valuesInAxis.sort(function(a, b) {
return a - b;
});
var min = null;
for (var j = 1; j < valuesInAxis.length; ++j) {
var delta = valuesInAxis[j] - valuesInAxis[j - 1];
if (delta > 0) {
min = min === null ? delta : Math.min(min, delta);
}
}
axisMinGaps[key] = min;
}
}
}
return axisMinGaps;
}
function makeColumnLayout(barSeries) {
var axisMinGaps = getValueAxesMinGaps(barSeries);
var seriesInfoList = [];
each(barSeries, function(seriesModel) {
var cartesian = seriesModel.coordinateSystem;
var baseAxis = cartesian.getBaseAxis();
var axisExtent = baseAxis.getExtent();
var bandWidth;
if (baseAxis.type === "category") {
bandWidth = baseAxis.getBandWidth();
} else if (baseAxis.type === "value" || baseAxis.type === "time") {
var key = baseAxis.dim + "_" + baseAxis.index;
var minGap = axisMinGaps[key];
var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]);
var scale = baseAxis.scale.getExtent();
var scaleSpan = Math.abs(scale[1] - scale[0]);
bandWidth = minGap ? extentSpan / scaleSpan * minGap : extentSpan;
} else {
var data = seriesModel.getData();
bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count();
}
var barWidth = parsePercent(seriesModel.get("barWidth"), bandWidth);
var barMaxWidth = parsePercent(seriesModel.get("barMaxWidth"), bandWidth);
var barMinWidth = parsePercent(
seriesModel.get("barMinWidth") || (isInLargeMode(seriesModel) ? 0.5 : 1),
bandWidth
);
var barGap = seriesModel.get("barGap");
var barCategoryGap = seriesModel.get("barCategoryGap");
seriesInfoList.push({
bandWidth,
barWidth,
barMaxWidth,
barMinWidth,
barGap,
barCategoryGap,
axisKey: getAxisKey(baseAxis),
stackId: getSeriesStackId(seriesModel)
});
});
return doCalBarWidthAndOffset(seriesInfoList);
}
function doCalBarWidthAndOffset(seriesInfoList) {
var columnsMap = {};
each(seriesInfoList, function(seriesInfo, idx) {
var axisKey = seriesInfo.axisKey;
var bandWidth = seriesInfo.bandWidth;
var columnsOnAxis = columnsMap[axisKey] || {
bandWidth,
remainedWidth: bandWidth,
autoWidthCount: 0,
categoryGap: null,
gap: "20%",
stacks: {}
};
var stacks = columnsOnAxis.stacks;
columnsMap[axisKey] = columnsOnAxis;
var stackId = seriesInfo.stackId;
if (!stacks[stackId]) {
columnsOnAxis.autoWidthCount++;
}
stacks[stackId] = stacks[stackId] || {
width: 0,
maxWidth: 0
};
var barWidth = seriesInfo.barWidth;
if (barWidth && !stacks[stackId].width) {
stacks[stackId].width = barWidth;
barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
columnsOnAxis.remainedWidth -= barWidth;
}
var barMaxWidth = seriesInfo.barMaxWidth;
barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
var barMinWidth = seriesInfo.barMinWidth;
barMinWidth && (stacks[stackId].minWidth = barMinWidth);
var barGap = seriesInfo.barGap;
barGap != null && (columnsOnAxis.gap = barGap);
var barCategoryGap = seriesInfo.barCategoryGap;
barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap);
});
var result = {};
each(columnsMap, function(columnsOnAxis, coordSysName) {
result[coordSysName] = {};
var stacks = columnsOnAxis.stacks;
var bandWidth = columnsOnAxis.bandWidth;
var categoryGapPercent = columnsOnAxis.categoryGap;
if (categoryGapPercent == null) {
var columnCount = keys(stacks).length;
categoryGapPercent = Math.max(35 - columnCount * 4, 15) + "%";
}
var categoryGap = parsePercent(categoryGapPercent, 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);
each(stacks, function(column) {
var maxWidth = column.maxWidth;
var minWidth = column.minWidth;
if (!column.width) {
var finalWidth = autoWidth;
if (maxWidth && maxWidth < finalWidth) {
finalWidth = Math.min(maxWidth, remainedWidth);
}
if (minWidth && minWidth > finalWidth) {
finalWidth = minWidth;
}
if (finalWidth !== autoWidth) {
column.width = finalWidth;
remainedWidth -= finalWidth + barGapPercent * finalWidth;
autoWidthCount--;
}
} else {
var finalWidth = column.width;
if (maxWidth) {
finalWidth = Math.min(finalWidth, maxWidth);
}
if (minWidth) {
finalWidth = Math.max(finalWidth, minWidth);
}
column.width = finalWidth;
remainedWidth -= finalWidth + barGapPercent * finalWidth;
autoWidthCount--;
}
});
autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
autoWidth = Math.max(autoWidth, 0);
var widthSum = 0;
var lastColumn;
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;
each(stacks, function(column, stackId) {
result[coordSysName][stackId] = result[coordSysName][stackId] || {
bandWidth,
offset,
width: column.width
};
offset += column.width * (1 + barGapPercent);
});
});
return result;
}
function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) {
if (barWidthAndOffset && axis) {
var result = barWidthAndOffset[getAxisKey(axis)];
if (result != null && seriesModel != null) {
return result[getSeriesStackId(seriesModel)];
}
return result;
}
}
function layout(seriesType, ecModel) {
var seriesModels = prepareLayoutBarSeries(seriesType, ecModel);
var barWidthAndOffset = makeColumnLayout(seriesModels);
each(seriesModels, function(seriesModel) {
var data = seriesModel.getData();
var cartesian = seriesModel.coordinateSystem;
var baseAxis = cartesian.getBaseAxis();
var stackId = getSeriesStackId(seriesModel);
var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId];
var columnOffset = columnLayoutInfo.offset;
var columnWidth = columnLayoutInfo.width;
data.setLayout({
bandWidth: columnLayoutInfo.bandWidth,
offset: columnOffset,
size: columnWidth
});
});
}
function createProgressiveLayout(seriesType) {
return {
seriesType,
plan: createRenderPlanner(),
reset: function(seriesModel) {
if (!isOnCartesian(seriesModel)) {
return;
}
var data = seriesModel.getData();
var cartesian = seriesModel.coordinateSystem;
var baseAxis = cartesian.getBaseAxis();
var valueAxis = cartesian.getOtherAxis(baseAxis);
var valueDimIdx = data.getDimensionIndex(data.mapDimension(valueAxis.dim));
var baseDimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim));
var drawBackground = seriesModel.get("showBackground", true);
var valueDim = data.mapDimension(valueAxis.dim);
var stackResultDim = data.getCalculationInfo("stackResultDimension");
var stacked = isDimensionStacked(data, valueDim) && !!data.getCalculationInfo("stackedOnSeries");
var isValueAxisH = valueAxis.isHorizontal();
var valueAxisStart = getValueAxisStart(baseAxis, valueAxis);
var isLarge = isInLargeMode(seriesModel);
var barMinHeight = seriesModel.get("barMinHeight") || 0;
var stackedDimIdx = stackResultDim && data.getDimensionIndex(stackResultDim);
var columnWidth = data.getLayout("size");
var columnOffset = data.getLayout("offset");
return {
progress: function(params, data2) {
var count = params.count;
var largePoints = isLarge && createFloat32Array(count * 3);
var largeBackgroundPoints = isLarge && drawBackground && createFloat32Array(count * 3);
var largeDataIndices = isLarge && createFloat32Array(count);
var coordLayout = cartesian.master.getRect();
var bgSize = isValueAxisH ? coordLayout.width : coordLayout.height;
var dataIndex;
var store = data2.getStore();
var idxOffset = 0;
while ((dataIndex = params.next()) != null) {
var value = store.get(stacked ? stackedDimIdx : valueDimIdx, dataIndex);
var baseValue = store.get(baseDimIdx, dataIndex);
var baseCoord = valueAxisStart;
var startValue = void 0;
if (stacked) {
startValue = +value - store.get(valueDimIdx, dataIndex);
}
var x = void 0;
var y = void 0;
var width = void 0;
var height = void 0;
if (isValueAxisH) {
var coord = cartesian.dataToPoint([value, baseValue]);
if (stacked) {
var startCoord = cartesian.dataToPoint([startValue, baseValue]);
baseCoord = startCoord[0];
}
x = baseCoord;
y = coord[1] + columnOffset;
width = coord[0] - baseCoord;
height = columnWidth;
if (Math.abs(width) < barMinHeight) {
width = (width < 0 ? -1 : 1) * barMinHeight;
}
} else {
var coord = cartesian.dataToPoint([baseValue, value]);
if (stacked) {
var startCoord = cartesian.dataToPoint([baseValue, startValue]);
baseCoord = startCoord[1];
}
x = coord[0] + columnOffset;
y = baseCoord;
width = columnWidth;
height = coord[1] - baseCoord;
if (Math.abs(height) < barMinHeight) {
height = (height <= 0 ? -1 : 1) * barMinHeight;
}
}
if (!isLarge) {
data2.setItemLayout(dataIndex, {
x,
y,
width,
height
});
} else {
largePoints[idxOffset] = x;
largePoints[idxOffset + 1] = y;
largePoints[idxOffset + 2] = isValueAxisH ? width : height;
if (largeBackgroundPoints) {
largeBackgroundPoints[idxOffset] = isValueAxisH ? coordLayout.x : x;
largeBackgroundPoints[idxOffset + 1] = isValueAxisH ? y : coordLayout.y;
largeBackgroundPoints[idxOffset + 2] = bgSize;
}
largeDataIndices[dataIndex] = dataIndex;
}
idxOffset += 3;
}
if (isLarge) {
data2.setLayout({
largePoints,
largeDataIndices,
largeBackgroundPoints,
valueAxisHorizontal: isValueAxisH
});
}
}
};
}
};
}
function isOnCartesian(seriesModel) {
return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === "cartesian2d";
}
function isInLargeMode(seriesModel) {
return seriesModel.pipelineContext && seriesModel.pipelineContext.large;
}
function getValueAxisStart(baseAxis, valueAxis) {
return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === "log" ? 1 : 0));
}
export { createProgressiveLayout, getLayoutOnAxis, layout, makeColumnLayout, prepareLayoutBarSeries, retrieveColumnLayout };