UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

384 lines (383 loc) 14.2 kB
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 };