| /* |
| * 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. |
| */ |
| |
| /** |
| * Helper for model references. |
| * There are many manners to refer axis/coordSys. |
| */ |
| |
| // TODO |
| // merge relevant logic to this file? |
| // check: "modelHelper" of tooltip and "BrushTargetManager". |
| |
| import {createHashMap, retrieve, each, HashMap} from 'zrender/src/core/util'; |
| import SeriesModel from './Series'; |
| import type PolarModel from '../coord/polar/PolarModel'; |
| import type { SeriesOption, SeriesOnCartesianOptionMixin } from '../util/types'; |
| import type { AxisBaseModel } from '../coord/AxisBaseModel'; |
| import { SINGLE_REFERRING } from '../util/model'; |
| import { ParallelSeriesOption } from '../chart/parallel/ParallelSeries'; |
| import ParallelModel from '../coord/parallel/ParallelModel'; |
| import ParallelAxisModel from '../coord/parallel/AxisModel'; |
| |
| /** |
| * @class |
| * For example: |
| * { |
| * coordSysName: 'cartesian2d', |
| * coordSysDims: ['x', 'y', ...], |
| * axisMap: HashMap({ |
| * x: xAxisModel, |
| * y: yAxisModel |
| * }), |
| * categoryAxisMap: HashMap({ |
| * x: xAxisModel, |
| * y: undefined |
| * }), |
| * // The index of the first category axis in `coordSysDims`. |
| * // `null/undefined` means no category axis exists. |
| * firstCategoryDimIndex: 1, |
| * // To replace user specified encode. |
| * } |
| */ |
| |
| class CoordSysInfo { |
| |
| coordSysName: string; |
| |
| coordSysDims: string[] = []; |
| |
| axisMap = createHashMap<AxisBaseModel>(); |
| |
| categoryAxisMap = createHashMap<AxisBaseModel>(); |
| |
| firstCategoryDimIndex: number; |
| |
| constructor(coordSysName: string) { |
| this.coordSysName = coordSysName; |
| } |
| } |
| |
| type SupportedCoordSys = 'cartesian2d' | 'polar' | 'singleAxis' | 'geo' | 'parallel'; |
| type Fetcher = ( |
| seriesModel: SeriesModel, |
| result: CoordSysInfo, |
| axisMap: HashMap<AxisBaseModel>, |
| categoryAxisMap: HashMap<AxisBaseModel> |
| ) => void; |
| |
| export function getCoordSysInfoBySeries(seriesModel: SeriesModel) { |
| const coordSysName = seriesModel.get('coordinateSystem') as SupportedCoordSys; |
| const result = new CoordSysInfo(coordSysName); |
| const fetch = fetchers[coordSysName]; |
| if (fetch) { |
| fetch(seriesModel, result, result.axisMap, result.categoryAxisMap); |
| return result; |
| } |
| } |
| |
| const fetchers: Record<SupportedCoordSys, Fetcher> = { |
| |
| cartesian2d: function ( |
| seriesModel: SeriesModel<SeriesOption & SeriesOnCartesianOptionMixin>, result, axisMap, categoryAxisMap |
| ) { |
| const xAxisModel = seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0] as AxisBaseModel; |
| const yAxisModel = seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0] as AxisBaseModel; |
| |
| if (__DEV__) { |
| if (!xAxisModel) { |
| throw new Error('xAxis "' + retrieve<number | string>( |
| seriesModel.get('xAxisIndex'), |
| seriesModel.get('xAxisId'), |
| 0 |
| ) + '" not found'); |
| } |
| if (!yAxisModel) { |
| throw new Error('yAxis "' + retrieve<number | string>( |
| seriesModel.get('xAxisIndex'), |
| seriesModel.get('yAxisId'), |
| 0 |
| ) + '" not found'); |
| } |
| } |
| |
| result.coordSysDims = ['x', 'y']; |
| axisMap.set('x', xAxisModel); |
| axisMap.set('y', yAxisModel); |
| |
| if (isCategory(xAxisModel)) { |
| categoryAxisMap.set('x', xAxisModel); |
| result.firstCategoryDimIndex = 0; |
| } |
| if (isCategory(yAxisModel)) { |
| categoryAxisMap.set('y', yAxisModel); |
| result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); |
| } |
| }, |
| |
| singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) { |
| const singleAxisModel = seriesModel.getReferringComponents( |
| 'singleAxis', SINGLE_REFERRING |
| ).models[0] as AxisBaseModel; |
| |
| if (__DEV__) { |
| if (!singleAxisModel) { |
| throw new Error('singleAxis should be specified.'); |
| } |
| } |
| |
| result.coordSysDims = ['single']; |
| axisMap.set('single', singleAxisModel); |
| |
| if (isCategory(singleAxisModel)) { |
| categoryAxisMap.set('single', singleAxisModel); |
| result.firstCategoryDimIndex = 0; |
| } |
| }, |
| |
| polar: function (seriesModel, result, axisMap, categoryAxisMap) { |
| const polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0] as PolarModel; |
| const radiusAxisModel = polarModel.findAxisModel('radiusAxis'); |
| const angleAxisModel = polarModel.findAxisModel('angleAxis'); |
| |
| if (__DEV__) { |
| if (!angleAxisModel) { |
| throw new Error('angleAxis option not found'); |
| } |
| if (!radiusAxisModel) { |
| throw new Error('radiusAxis option not found'); |
| } |
| } |
| |
| result.coordSysDims = ['radius', 'angle']; |
| axisMap.set('radius', radiusAxisModel); |
| axisMap.set('angle', angleAxisModel); |
| |
| if (isCategory(radiusAxisModel)) { |
| categoryAxisMap.set('radius', radiusAxisModel); |
| result.firstCategoryDimIndex = 0; |
| } |
| if (isCategory(angleAxisModel)) { |
| categoryAxisMap.set('angle', angleAxisModel); |
| result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); |
| } |
| }, |
| |
| geo: function (seriesModel, result, axisMap, categoryAxisMap) { |
| result.coordSysDims = ['lng', 'lat']; |
| }, |
| |
| parallel: function (seriesModel, result, axisMap, categoryAxisMap) { |
| const ecModel = seriesModel.ecModel; |
| const parallelModel = ecModel.getComponent( |
| 'parallel', (seriesModel as SeriesModel<ParallelSeriesOption>).get('parallelIndex') |
| ) as ParallelModel; |
| const coordSysDims = result.coordSysDims = parallelModel.dimensions.slice(); |
| |
| each(parallelModel.parallelAxisIndex, function (axisIndex, index) { |
| const axisModel = ecModel.getComponent('parallelAxis', axisIndex) as ParallelAxisModel; |
| const axisDim = coordSysDims[index]; |
| axisMap.set(axisDim, axisModel); |
| |
| if (isCategory(axisModel)) { |
| categoryAxisMap.set(axisDim, axisModel); |
| if (result.firstCategoryDimIndex == null) { |
| result.firstCategoryDimIndex = index; |
| } |
| } |
| }); |
| } |
| }; |
| |
| function isCategory(axisModel: AxisBaseModel) { |
| return axisModel.get('type') === 'category'; |
| } |
| |