diff --git a/src/chart/bar/BaseBarSeries.ts b/src/chart/bar/BaseBarSeries.ts index 8dad96d280..d798cb9b85 100644 --- a/src/chart/bar/BaseBarSeries.ts +++ b/src/chart/bar/BaseBarSeries.ts @@ -70,6 +70,10 @@ export interface BaseBarSeriesOption = BaseBarSeriesOption> @@ -121,4 +125,4 @@ class BaseBarSeriesModel = BaseBarSeri SeriesModel.registerClass(BaseBarSeriesModel); -export default BaseBarSeriesModel; \ No newline at end of file +export default BaseBarSeriesModel; diff --git a/src/layout/barGrid.ts b/src/layout/barGrid.ts index 9ca8442e9a..da3f169d78 100644 --- a/src/layout/barGrid.ts +++ b/src/layout/barGrid.ts @@ -17,7 +17,7 @@ * under the License. */ -import { each, defaults, keys } from 'zrender/src/core/util'; +import { each, defaults, keys, isNumber, clone } from 'zrender/src/core/util'; import { parsePercent } from '../util/number'; import { isDimensionStacked } from '../data/helper/dataStackHelper'; import createRenderPlanner from '../chart/helper/createRenderPlanner'; @@ -81,7 +81,36 @@ export interface BarGridLayoutOptionForCustomSeries { interface LayoutOption extends BarGridLayoutOptionForCustomSeries { axis: Axis2D } - +/** + * Intra group sorting interface-start + */ +interface layoutItemInfo { + dataIndex: number + value: number + baseValue: number + seriesIndex: number + [key: string]: any +} +interface layoutInfo { + orderLayoutDataList: Array> + noOrderLayoutDataList: Array> + columnOffsetList: Array + groupOrder?: 'asc' | 'desc' +} +interface layoutRenderItemInfo { + value?: number + baseValue?: number + columnOffset?: number, + [key: string]: any +} +let layoutInfo: layoutInfo = { + orderLayoutDataList: [], + noOrderLayoutDataList: [], + columnOffsetList: [] +}; +/** + * Intra group sorting interface-end + */ export type BarGridLayoutResult = BarWidthAndOffset[string][string][]; /** * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined. @@ -435,14 +464,21 @@ function retrieveColumnLayout( return result; } } -export {retrieveColumnLayout}; +export { retrieveColumnLayout }; export function layout(seriesType: string, ecModel: GlobalModel) { - const seriesModels = prepareLayoutBarSeries(seriesType, ecModel); const barWidthAndOffset = makeColumnLayout(seriesModels); - - each(seriesModels, function (seriesModel) { + if (seriesModels.length === 0) { + return; + } + layoutInfo = { + groupOrder: getSeriesGroupOrder(seriesModels), + orderLayoutDataList: [], + noOrderLayoutDataList: [], + columnOffsetList: [] + }; + each(seriesModels, function (seriesModel, index) { const data = seriesModel.getData(); const cartesian = seriesModel.coordinateSystem as Cartesian2D; @@ -450,17 +486,142 @@ export function layout(seriesType: string, ecModel: GlobalModel) { const stackId = getSeriesStackId(seriesModel); const columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; - const columnOffset = columnLayoutInfo.offset; - const columnWidth = columnLayoutInfo.width; data.setLayout({ bandWidth: columnLayoutInfo.bandWidth, - offset: columnOffset, - size: columnWidth + offset: columnLayoutInfo.offset, + size: columnLayoutInfo.width }); + collectingLayoutData(layoutInfo, seriesModel, index); }); + if (layoutInfo.groupOrder !== undefined) { + orderLayoutData(layoutInfo); + } +} +function getSeriesGroupOrder(seriesModels: BarSeriesModel[]) { + for (let i = 0; i < seriesModels.length; i++) { + const seriesOrder = seriesModels[i].get('groupOrder'); + if (seriesOrder !== undefined) { + return seriesOrder; + } + } } +function collectingLayoutData( + layoutInfo: layoutInfo, + seriesModel: BarSeriesModel, + index: number +) { + const data = seriesModel.getData(); + const seriesIndex = seriesModel.seriesIndex; + const cartesian = seriesModel.coordinateSystem as Cartesian2D; + const baseAxis = cartesian.getBaseAxis(); + const valueAxis = cartesian.getOtherAxis(baseAxis); + const valueDimIdx = data.getDimensionIndex(data.mapDimension(valueAxis.dim)); + const baseDimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim)); + const columnOffset = data.getLayout('offset'); + const stackId = getSeriesStackId(seriesModel); + const orderLayoutDataList = layoutInfo.orderLayoutDataList; + const noOrderLayoutDataList = layoutInfo.noOrderLayoutDataList; + const columnOffsetList = layoutInfo.columnOffsetList; + let layoutDataListItem: layoutItemInfo; + columnOffsetList[index] = columnOffset; + //The index value is for loop index, + //which is used to obtain the offset of the corresponding position when clicking on the legend to achieve the situation where the column is close + let value; + let baseValue; + const store = data.getStore(); + const seriesOrder = seriesModel.get('groupOrder'); + + for (let idx = 0, len = store.count(); idx < len; idx++) { + baseValue = store.get(baseDimIdx, idx) as number; + if (!isNumber(baseValue)) { + continue; + } + value = store.get(valueDimIdx, idx) as number; + layoutDataListItem = { + dataIndex: idx, + value: value, + stackId: stackId, + baseValue: baseValue, + seriesIndex: seriesIndex + }; + if (['asc', 'desc'].includes(seriesOrder)) { + if (orderLayoutDataList[baseValue] === undefined) { + orderLayoutDataList[baseValue] = []; + } + orderLayoutDataList[baseValue].push(clone(layoutDataListItem)); + layoutDataListItem.isOrderData = true; + } + //In the current stacked situation, if sorting and non sorting are mixed, + //it is necessary to add sorted data to non sorted data for the calculation of stacked data + if (noOrderLayoutDataList[baseValue] === undefined) { + noOrderLayoutDataList[baseValue] = []; + } + noOrderLayoutDataList[baseValue].push(layoutDataListItem); + } +} +function orderLayoutData(layoutInfo: layoutInfo) { + const groupOrder = layoutInfo.groupOrder; + const orderLayoutDataList = layoutInfo.orderLayoutDataList; + const columnOffsetList = layoutInfo.columnOffsetList; + columnOffsetList.sort((a, b) => a - b); + each(orderLayoutDataList, function (layoutDataListItem) { + layoutDataListItem.sort(function (a, b) { + if (groupOrder === 'desc') { + return b.value - a.value; + } + if (groupOrder === 'asc') { + return a.value - b.value; + } + }); + }); +} +function getLayoutRenderItemInfo(seriesIndex: number, dataIndex: number, value: number, stackId: string): layoutRenderItemInfo { + const layoutDataList = [].concat(layoutInfo.orderLayoutDataList, layoutInfo.noOrderLayoutDataList); + const columnOffsetList = layoutInfo.columnOffsetList; + let layoutRenderItemInfo: layoutRenderItemInfo = {}; + for (let i = 0; i < layoutDataList.length; i++) { + if (layoutDataList[i] === undefined) { + continue; + } + layoutRenderItemInfo = doGetLayoutRenderItemInfo(seriesIndex, dataIndex, value, layoutDataList[i], columnOffsetList, stackId); + if (layoutRenderItemInfo.columnOffset === undefined) { + continue; + } + return layoutRenderItemInfo; + } + return layoutRenderItemInfo; +} +function doGetLayoutRenderItemInfo( + seriesIndex: number, + dataIndex: number, + value: number, + layoutDataSingleList: layoutItemInfo[], + columnOffsetList: Array, + stackId: string +): layoutRenderItemInfo { + let startValue = 0; + for (let i = 0; i < layoutDataSingleList.length; i++) { + const dataItem = layoutDataSingleList[i]; + if ( + !dataItem.isOrderData && + dataItem.dataIndex === dataIndex && + dataItem.seriesIndex === seriesIndex + ) { + return { + value: dataItem.value, + baseValue: dataItem.baseValue, + startValue: startValue, + columnOffset: columnOffsetList[i] + }; + } + if (value * dataItem.value >= 0 && dataItem.stackId === stackId) { + startValue += dataItem.value; + } + } + return {}; +} // TODO: Do not support stack in large mode yet. export function createProgressiveLayout(seriesType: string): StageHandler { return { @@ -475,26 +636,24 @@ export function createProgressiveLayout(seriesType: string): StageHandler { const data = seriesModel.getData(); + const seriesIndex = seriesModel.seriesIndex; + const cartesian = seriesModel.coordinateSystem as Cartesian2D; const baseAxis = cartesian.getBaseAxis(); const valueAxis = cartesian.getOtherAxis(baseAxis); const valueDimIdx = data.getDimensionIndex(data.mapDimension(valueAxis.dim)); - const baseDimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim)); + const drawBackground = seriesModel.get('showBackground', true); const valueDim = data.mapDimension(valueAxis.dim); - const stackResultDim = data.getCalculationInfo('stackResultDimension'); - const stacked = isDimensionStacked(data, valueDim) && !!data.getCalculationInfo('stackedOnSeries'); + const stacked = isDimensionStacked(data, valueDim); + const stackId = getSeriesStackId(seriesModel); const isValueAxisH = valueAxis.isHorizontal(); const valueAxisStart = getValueAxisStart(baseAxis, valueAxis); const isLarge = isInLargeMode(seriesModel); const barMinHeight = seriesModel.get('barMinHeight') || 0; - - const stackedDimIdx = stackResultDim && data.getDimensionIndex(stackResultDim); - // Layout info. const columnWidth = data.getLayout('size'); - const columnOffset = data.getLayout('offset'); - + // const columnOffset = data.getLayout('offset'); return { progress: function (params, data) { const count = params.count; @@ -510,25 +669,28 @@ export function createProgressiveLayout(seriesType: string): StageHandler { let idxOffset = 0; while ((dataIndex = params.next()) != null) { - const value = store.get(stacked ? stackedDimIdx : valueDimIdx, dataIndex); - const baseValue = store.get(baseDimIdx, dataIndex) as number; - + const value = store.get(valueDimIdx, dataIndex) as number; + const layoutRenderItemInfo = getLayoutRenderItemInfo(seriesIndex, dataIndex, value, stackId); + const columnOffset = layoutRenderItemInfo.columnOffset; + if (columnOffset === undefined) { + continue; + } + const baseValue = layoutRenderItemInfo.baseValue; let baseCoord = valueAxisStart; - let startValue; + let startValue = 0; // Because of the barMinHeight, we can not use the value in // stackResultDimension directly. if (stacked) { - startValue = +value - (store.get(valueDimIdx, dataIndex) as number); + startValue = layoutRenderItemInfo.startValue; } - let x; let y; let width; let height; if (isValueAxisH) { - const coord = cartesian.dataToPoint([value, baseValue]); + const coord = cartesian.dataToPoint([value + startValue, baseValue]); if (stacked) { const startCoord = cartesian.dataToPoint([startValue, baseValue]); baseCoord = startCoord[0]; @@ -543,7 +705,7 @@ export function createProgressiveLayout(seriesType: string): StageHandler { } } else { - const coord = cartesian.dataToPoint([baseValue, value]); + const coord = cartesian.dataToPoint([baseValue, value + startValue]); if (stacked) { const startCoord = cartesian.dataToPoint([baseValue, startValue]); baseCoord = startCoord[1]; @@ -578,7 +740,6 @@ export function createProgressiveLayout(seriesType: string): StageHandler { idxOffset += 3; } - if (isLarge) { data.setLayout({ largePoints, diff --git a/test/bar-groupOrder.html b/test/bar-groupOrder.html new file mode 100644 index 0000000000..e8d1fed06b --- /dev/null +++ b/test/bar-groupOrder.html @@ -0,0 +1,989 @@ + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + +