blob: a3c62c890a4df37536175b3efb51649d0d9cc8d6 [file] [log] [blame]
/*
* 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';
}