Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/chart/bar/BaseBarSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export interface BaseBarSeriesOption<StateOption, ExtraStateOption = DefaultStat

large?: boolean
largeThreshold?: number
/**
* Ascending or descending within a group
*/
groupOrder?: 'asc' | 'desc'
}

class BaseBarSeriesModel<Opts extends BaseBarSeriesOption<unknown> = BaseBarSeriesOption<unknown>>
Expand Down Expand Up @@ -121,4 +125,4 @@ class BaseBarSeriesModel<Opts extends BaseBarSeriesOption<unknown> = BaseBarSeri

SeriesModel.registerClass(BaseBarSeriesModel);

export default BaseBarSeriesModel;
export default BaseBarSeriesModel;
215 changes: 188 additions & 27 deletions src/layout/barGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<Array<layoutItemInfo>>
noOrderLayoutDataList: Array<Array<layoutItemInfo>>
columnOffsetList: Array<number>
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.
Expand Down Expand Up @@ -435,32 +464,164 @@ 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;
const baseAxis = cartesian.getBaseAxis();

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<number>,
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 {
Expand All @@ -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;
Expand All @@ -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];
Expand All @@ -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];
Expand Down Expand Up @@ -578,7 +740,6 @@ export function createProgressiveLayout(seriesType: string): StageHandler {

idxOffset += 3;
}

if (isLarge) {
data.setLayout({
largePoints,
Expand Down
Loading