LoCs / echarts-5.5.0-rc.2 /src /data /helper /dimensionHelper.ts
ZoeDuan's picture
Upload 1382 files
4bb817b verified
raw
history blame
8 kB
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import {each, createHashMap, assert, map} from 'zrender/src/core/util';
import SeriesData from '../SeriesData';
import {
DimensionName, VISUAL_DIMENSIONS, DimensionType, DimensionIndex
} from '../../util/types';
import { DataStoreDimensionType } from '../DataStore';
import { SeriesDataSchema } from './SeriesDataSchema';
export type DimensionSummaryEncode = {
defaultedLabel: DimensionName[],
defaultedTooltip: DimensionName[],
[coordOrVisualDimName: string]:
// index: coordDimIndex, value: dataDimName
DimensionName[]
};
export type DimensionSummary = {
encode: DimensionSummaryEncode,
// Those details that can be expose to users are put int `userOutput`.
userOutput: DimensionUserOuput,
// All of the data dim names that mapped by coordDim.
dataDimsOnCoord: DimensionName[],
dataDimIndicesOnCoord: DimensionIndex[],
encodeFirstDimNotExtra: {[coordDim: string]: DimensionName},
};
export type DimensionUserOuputEncode = {
// index: coordDimIndex, value: dataDimIndex
[coordOrVisualDimName: string]: DimensionIndex[]
};
class DimensionUserOuput {
private _encode: DimensionUserOuputEncode;
private _cachedDimNames: DimensionName[];
private _schema?: SeriesDataSchema;
constructor(
encode: DimensionUserOuputEncode,
dimRequest?: SeriesDataSchema
) {
this._encode = encode;
this._schema = dimRequest;
}
get(): {
fullDimensions: DimensionName[];
encode: DimensionUserOuputEncode;
} {
return {
// Do not generate full dimension name until fist used.
fullDimensions: this._getFullDimensionNames(),
encode: this._encode
};
}
/**
* Get all data store dimension names.
* Theoretically a series data store is defined both by series and used dataset (if any).
* If some dimensions are omitted for performance reason in `this.dimensions`,
* the dimension name may not be auto-generated if user does not specify a dimension name.
* In this case, the dimension name is `null`/`undefined`.
*/
private _getFullDimensionNames(): DimensionName[] {
if (!this._cachedDimNames) {
this._cachedDimNames = this._schema
? this._schema.makeOutputDimensionNames()
: [];
}
return this._cachedDimNames;
}
};
export function summarizeDimensions(
data: SeriesData,
schema?: SeriesDataSchema
): DimensionSummary {
const summary: DimensionSummary = {} as DimensionSummary;
const encode = summary.encode = {} as DimensionSummaryEncode;
const notExtraCoordDimMap = createHashMap<1, DimensionName>();
let defaultedLabel = [] as DimensionName[];
let defaultedTooltip = [] as DimensionName[];
const userOutputEncode = {} as DimensionUserOuputEncode;
each(data.dimensions, function (dimName) {
const dimItem = data.getDimensionInfo(dimName);
const coordDim = dimItem.coordDim;
if (coordDim) {
if (__DEV__) {
assert(VISUAL_DIMENSIONS.get(coordDim as any) == null);
}
const coordDimIndex = dimItem.coordDimIndex;
getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName;
if (!dimItem.isExtraCoord) {
notExtraCoordDimMap.set(coordDim, 1);
// Use the last coord dim (and label friendly) as default label,
// because when dataset is used, it is hard to guess which dimension
// can be value dimension. If both show x, y on label is not look good,
// and conventionally y axis is focused more.
if (mayLabelDimType(dimItem.type)) {
defaultedLabel[0] = dimName;
}
// User output encode do not contain generated coords.
// And it only has index. User can use index to retrieve value from the raw item array.
getOrCreateEncodeArr(userOutputEncode, coordDim)[coordDimIndex] =
data.getDimensionIndex(dimItem.name);
}
if (dimItem.defaultTooltip) {
defaultedTooltip.push(dimName);
}
}
VISUAL_DIMENSIONS.each(function (v, otherDim) {
const encodeArr = getOrCreateEncodeArr(encode, otherDim);
const dimIndex = dimItem.otherDims[otherDim];
if (dimIndex != null && dimIndex !== false) {
encodeArr[dimIndex] = dimItem.name;
}
});
});
let dataDimsOnCoord = [] as DimensionName[];
const encodeFirstDimNotExtra = {} as {[coordDim: string]: DimensionName};
notExtraCoordDimMap.each(function (v, coordDim) {
const dimArr = encode[coordDim];
encodeFirstDimNotExtra[coordDim] = dimArr[0];
// Not necessary to remove duplicate, because a data
// dim canot on more than one coordDim.
dataDimsOnCoord = dataDimsOnCoord.concat(dimArr);
});
summary.dataDimsOnCoord = dataDimsOnCoord;
summary.dataDimIndicesOnCoord = map(
dataDimsOnCoord, dimName => data.getDimensionInfo(dimName).storeDimIndex
);
summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra;
const encodeLabel = encode.label;
// FIXME `encode.label` is not recommended, because formatter cannot be set
// in this way. Use label.formatter instead. Maybe remove this approach someday.
if (encodeLabel && encodeLabel.length) {
defaultedLabel = encodeLabel.slice();
}
const encodeTooltip = encode.tooltip;
if (encodeTooltip && encodeTooltip.length) {
defaultedTooltip = encodeTooltip.slice();
}
else if (!defaultedTooltip.length) {
defaultedTooltip = defaultedLabel.slice();
}
encode.defaultedLabel = defaultedLabel;
encode.defaultedTooltip = defaultedTooltip;
summary.userOutput = new DimensionUserOuput(userOutputEncode, schema);
return summary;
}
function getOrCreateEncodeArr(
encode: DimensionSummaryEncode | DimensionUserOuputEncode, dim: DimensionName
): (DimensionIndex | DimensionName)[] {
if (!encode.hasOwnProperty(dim)) {
encode[dim] = [];
}
return encode[dim];
}
// FIXME:TS should be type `AxisType`
export function getDimensionTypeByAxis(axisType: string): DataStoreDimensionType {
return axisType === 'category'
? 'ordinal'
: axisType === 'time'
? 'time'
: 'float';
}
function mayLabelDimType(dimType: DimensionType): boolean {
// In most cases, ordinal and time do not suitable for label.
// Ordinal info can be displayed on axis. Time is too long.
return !(dimType === 'ordinal' || dimType === 'time');
}
// function findTheLastDimMayLabel(data) {
// // Get last value dim
// let dimensions = data.dimensions.slice();
// let valueType;
// let valueDim;
// while (dimensions.length && (
// valueDim = dimensions.pop(),
// valueType = data.getDimensionInfo(valueDim).type,
// valueType === 'ordinal' || valueType === 'time'
// )) {} // jshint ignore:line
// return valueDim;
// }