Spaces:
Running
Running
| /* | |
| * 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, isString} from 'zrender/src/core/util'; | |
| import SeriesDimensionDefine from '../SeriesDimensionDefine'; | |
| import SeriesModel from '../../model/Series'; | |
| import SeriesData, { DataCalculationInfo } from '../SeriesData'; | |
| import type { SeriesOption, SeriesStackOptionMixin, DimensionName } from '../../util/types'; | |
| import { isSeriesDataSchema, SeriesDataSchema } from './SeriesDataSchema'; | |
| import DataStore from '../DataStore'; | |
| type EnableDataStackDimensionsInput = { | |
| schema: SeriesDataSchema; | |
| // If given, stack dimension will be ensured on this store. | |
| // Otherwise, stack dimension will be appended at the tail, and should not | |
| // be used on a shared store, but should create a brand new storage later. | |
| store?: DataStore; | |
| }; | |
| type EnableDataStackDimensionsInputLegacy = (SeriesDimensionDefine | string)[]; | |
| /** | |
| * Note that it is too complicated to support 3d stack by value | |
| * (have to create two-dimension inverted index), so in 3d case | |
| * we just support that stacked by index. | |
| * | |
| * @param seriesModel | |
| * @param dimensionsInput The same as the input of <module:echarts/data/SeriesData>. | |
| * The input will be modified. | |
| * @param opt | |
| * @param opt.stackedCoordDimension Specify a coord dimension if needed. | |
| * @param opt.byIndex=false | |
| * @return calculationInfo | |
| * { | |
| * stackedDimension: string | |
| * stackedByDimension: string | |
| * isStackedByIndex: boolean | |
| * stackedOverDimension: string | |
| * stackResultDimension: string | |
| * } | |
| */ | |
| export function enableDataStack( | |
| seriesModel: SeriesModel<SeriesOption & SeriesStackOptionMixin>, | |
| dimensionsInput: EnableDataStackDimensionsInput | EnableDataStackDimensionsInputLegacy, | |
| opt?: { | |
| // Backward compat | |
| stackedCoordDimension?: string | |
| byIndex?: boolean | |
| } | |
| ): Pick< | |
| DataCalculationInfo<unknown>, | |
| 'stackedDimension' | |
| | 'stackedByDimension' | |
| | 'isStackedByIndex' | |
| | 'stackedOverDimension' | |
| | 'stackResultDimension' | |
| > { | |
| opt = opt || {}; | |
| let byIndex = opt.byIndex; | |
| const stackedCoordDimension = opt.stackedCoordDimension; | |
| let dimensionDefineList: EnableDataStackDimensionsInputLegacy; | |
| let schema: SeriesDataSchema; | |
| let store: DataStore; | |
| if (isLegacyDimensionsInput(dimensionsInput)) { | |
| dimensionDefineList = dimensionsInput; | |
| } | |
| else { | |
| schema = dimensionsInput.schema; | |
| dimensionDefineList = schema.dimensions; | |
| store = dimensionsInput.store; | |
| } | |
| // Compatibal: when `stack` is set as '', do not stack. | |
| const mayStack = !!(seriesModel && seriesModel.get('stack')); | |
| let stackedByDimInfo: SeriesDimensionDefine; | |
| let stackedDimInfo: SeriesDimensionDefine; | |
| let stackResultDimension: string; | |
| let stackedOverDimension: string; | |
| each(dimensionDefineList, function (dimensionInfo, index) { | |
| if (isString(dimensionInfo)) { | |
| dimensionDefineList[index] = dimensionInfo = { | |
| name: dimensionInfo as string | |
| } as SeriesDimensionDefine; | |
| } | |
| if (mayStack && !dimensionInfo.isExtraCoord) { | |
| // Find the first ordinal dimension as the stackedByDimInfo. | |
| if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { | |
| stackedByDimInfo = dimensionInfo; | |
| } | |
| // Find the first stackable dimension as the stackedDimInfo. | |
| if (!stackedDimInfo | |
| && dimensionInfo.type !== 'ordinal' | |
| && dimensionInfo.type !== 'time' | |
| && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim) | |
| ) { | |
| stackedDimInfo = dimensionInfo; | |
| } | |
| } | |
| }); | |
| if (stackedDimInfo && !byIndex && !stackedByDimInfo) { | |
| // Compatible with previous design, value axis (time axis) only stack by index. | |
| // It may make sense if the user provides elaborately constructed data. | |
| byIndex = true; | |
| } | |
| // Add stack dimension, they can be both calculated by coordinate system in `unionExtent`. | |
| // That put stack logic in List is for using conveniently in echarts extensions, but it | |
| // might not be a good way. | |
| if (stackedDimInfo) { | |
| // Use a weird name that not duplicated with other names. | |
| // Also need to use seriesModel.id as postfix because different | |
| // series may share same data store. The stack dimension needs to be distinguished. | |
| stackResultDimension = '__\0ecstackresult_' + seriesModel.id; | |
| stackedOverDimension = '__\0ecstackedover_' + seriesModel.id; | |
| // Create inverted index to fast query index by value. | |
| if (stackedByDimInfo) { | |
| stackedByDimInfo.createInvertedIndices = true; | |
| } | |
| const stackedDimCoordDim = stackedDimInfo.coordDim; | |
| const stackedDimType = stackedDimInfo.type; | |
| let stackedDimCoordIndex = 0; | |
| each(dimensionDefineList, function (dimensionInfo: SeriesDimensionDefine) { | |
| if (dimensionInfo.coordDim === stackedDimCoordDim) { | |
| stackedDimCoordIndex++; | |
| } | |
| }); | |
| const stackedOverDimensionDefine: SeriesDimensionDefine = { | |
| name: stackResultDimension, | |
| coordDim: stackedDimCoordDim, | |
| coordDimIndex: stackedDimCoordIndex, | |
| type: stackedDimType, | |
| isExtraCoord: true, | |
| isCalculationCoord: true, | |
| storeDimIndex: dimensionDefineList.length | |
| }; | |
| const stackResultDimensionDefine: SeriesDimensionDefine = { | |
| name: stackedOverDimension, | |
| // This dimension contains stack base (generally, 0), so do not set it as | |
| // `stackedDimCoordDim` to avoid extent calculation, consider log scale. | |
| coordDim: stackedOverDimension, | |
| coordDimIndex: stackedDimCoordIndex + 1, | |
| type: stackedDimType, | |
| isExtraCoord: true, | |
| isCalculationCoord: true, | |
| storeDimIndex: dimensionDefineList.length + 1 | |
| }; | |
| if (schema) { | |
| if (store) { | |
| stackedOverDimensionDefine.storeDimIndex = | |
| store.ensureCalculationDimension(stackedOverDimension, stackedDimType); | |
| stackResultDimensionDefine.storeDimIndex = | |
| store.ensureCalculationDimension(stackResultDimension, stackedDimType); | |
| } | |
| schema.appendCalculationDimension(stackedOverDimensionDefine); | |
| schema.appendCalculationDimension(stackResultDimensionDefine); | |
| } | |
| else { | |
| dimensionDefineList.push(stackedOverDimensionDefine); | |
| dimensionDefineList.push(stackResultDimensionDefine); | |
| } | |
| } | |
| return { | |
| stackedDimension: stackedDimInfo && stackedDimInfo.name, | |
| stackedByDimension: stackedByDimInfo && stackedByDimInfo.name, | |
| isStackedByIndex: byIndex, | |
| stackedOverDimension: stackedOverDimension, | |
| stackResultDimension: stackResultDimension | |
| }; | |
| } | |
| function isLegacyDimensionsInput( | |
| dimensionsInput: Parameters<typeof enableDataStack>[1] | |
| ): dimensionsInput is EnableDataStackDimensionsInputLegacy { | |
| return !isSeriesDataSchema((dimensionsInput as EnableDataStackDimensionsInput).schema); | |
| } | |
| export function isDimensionStacked(data: SeriesData, stackedDim: string): boolean { | |
| // Each single series only maps to one pair of axis. So we do not need to | |
| // check stackByDim, whatever stacked by a dimension or stacked by index. | |
| return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension'); | |
| } | |
| export function getStackedDimension(data: SeriesData, targetDim: string): DimensionName { | |
| return isDimensionStacked(data, targetDim) | |
| ? data.getCalculationInfo('stackResultDimension') | |
| : targetDim; | |
| } | |