| /* | |
| * 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. | |
| */ | |
| /** | |
| * Single coordinates system. | |
| */ | |
| import SingleAxis from './SingleAxis'; | |
| import * as axisHelper from '../axisHelper'; | |
| import {getLayoutRect} from '../../util/layout'; | |
| import {each} from 'zrender/src/core/util'; | |
| import { CoordinateSystem, CoordinateSystemMaster } from '../CoordinateSystem'; | |
| import GlobalModel from '../../model/Global'; | |
| import ExtensionAPI from '../../core/ExtensionAPI'; | |
| import BoundingRect from 'zrender/src/core/BoundingRect'; | |
| import SingleAxisModel from './AxisModel'; | |
| import { ParsedModelFinder, ParsedModelFinderKnown } from '../../util/model'; | |
| import { ScaleDataValue } from '../../util/types'; | |
| import { AxisBaseModel } from '../AxisBaseModel'; | |
| import { CategoryAxisBaseOption } from '../axisCommonTypes'; | |
| export const singleDimensions = ['single']; | |
| /** | |
| * Create a single coordinates system. | |
| */ | |
| class Single implements CoordinateSystem, CoordinateSystemMaster { | |
| readonly type = 'single'; | |
| readonly dimension = 'single'; | |
| /** | |
| * Add it just for draw tooltip. | |
| */ | |
| readonly dimensions = singleDimensions; | |
| name: string; | |
| axisPointerEnabled: boolean = true; | |
| model: SingleAxisModel; | |
| private _axis: SingleAxis; | |
| private _rect: BoundingRect; | |
| constructor(axisModel: SingleAxisModel, ecModel: GlobalModel, api: ExtensionAPI) { | |
| this.model = axisModel; | |
| this._init(axisModel, ecModel, api); | |
| } | |
| /** | |
| * Initialize single coordinate system. | |
| */ | |
| _init(axisModel: SingleAxisModel, ecModel: GlobalModel, api: ExtensionAPI) { | |
| const dim = this.dimension; | |
| const axis = new SingleAxis( | |
| dim, | |
| axisHelper.createScaleByModel(axisModel), | |
| [0, 0], | |
| axisModel.get('type'), | |
| axisModel.get('position') | |
| ); | |
| const isCategory = axis.type === 'category'; | |
| axis.onBand = isCategory && (axisModel as AxisBaseModel<CategoryAxisBaseOption>).get('boundaryGap'); | |
| axis.inverse = axisModel.get('inverse'); | |
| axis.orient = axisModel.get('orient'); | |
| axisModel.axis = axis; | |
| axis.model = axisModel; | |
| axis.coordinateSystem = this; | |
| this._axis = axis; | |
| } | |
| /** | |
| * Update axis scale after data processed | |
| */ | |
| update(ecModel: GlobalModel, api: ExtensionAPI) { | |
| ecModel.eachSeries(function (seriesModel) { | |
| if (seriesModel.coordinateSystem === this) { | |
| const data = seriesModel.getData(); | |
| each(data.mapDimensionsAll(this.dimension), function (dim) { | |
| this._axis.scale.unionExtentFromData(data, dim); | |
| }, this); | |
| axisHelper.niceScaleExtent(this._axis.scale, this._axis.model); | |
| } | |
| }, this); | |
| } | |
| /** | |
| * Resize the single coordinate system. | |
| */ | |
| resize(axisModel: SingleAxisModel, api: ExtensionAPI) { | |
| this._rect = getLayoutRect( | |
| { | |
| left: axisModel.get('left'), | |
| top: axisModel.get('top'), | |
| right: axisModel.get('right'), | |
| bottom: axisModel.get('bottom'), | |
| width: axisModel.get('width'), | |
| height: axisModel.get('height') | |
| }, | |
| { | |
| width: api.getWidth(), | |
| height: api.getHeight() | |
| } | |
| ); | |
| this._adjustAxis(); | |
| } | |
| getRect() { | |
| return this._rect; | |
| } | |
| private _adjustAxis() { | |
| const rect = this._rect; | |
| const axis = this._axis; | |
| const isHorizontal = axis.isHorizontal(); | |
| const extent = isHorizontal ? [0, rect.width] : [0, rect.height]; | |
| const idx = axis.inverse ? 1 : 0; | |
| axis.setExtent(extent[idx], extent[1 - idx]); | |
| this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y); | |
| } | |
| private _updateAxisTransform(axis: SingleAxis, coordBase: number) { | |
| const axisExtent = axis.getExtent(); | |
| const extentSum = axisExtent[0] + axisExtent[1]; | |
| const isHorizontal = axis.isHorizontal(); | |
| axis.toGlobalCoord = isHorizontal | |
| ? function (coord) { | |
| return coord + coordBase; | |
| } | |
| : function (coord) { | |
| return extentSum - coord + coordBase; | |
| }; | |
| axis.toLocalCoord = isHorizontal | |
| ? function (coord) { | |
| return coord - coordBase; | |
| } | |
| : function (coord) { | |
| return extentSum - coord + coordBase; | |
| }; | |
| } | |
| /** | |
| * Get axis. | |
| */ | |
| getAxis() { | |
| return this._axis; | |
| } | |
| /** | |
| * Get axis, add it just for draw tooltip. | |
| */ | |
| getBaseAxis() { | |
| return this._axis; | |
| } | |
| getAxes() { | |
| return [this._axis]; | |
| } | |
| getTooltipAxes() { | |
| return { | |
| baseAxes: [this.getAxis()], | |
| // Empty otherAxes | |
| otherAxes: [] as SingleAxis[] | |
| }; | |
| } | |
| /** | |
| * If contain point. | |
| */ | |
| containPoint(point: number[]) { | |
| const rect = this.getRect(); | |
| const axis = this.getAxis(); | |
| const orient = axis.orient; | |
| if (orient === 'horizontal') { | |
| return axis.contain(axis.toLocalCoord(point[0])) | |
| && (point[1] >= rect.y && point[1] <= (rect.y + rect.height)); | |
| } | |
| else { | |
| return axis.contain(axis.toLocalCoord(point[1])) | |
| && (point[0] >= rect.y && point[0] <= (rect.y + rect.height)); | |
| } | |
| } | |
| pointToData(point: number[]) { | |
| const axis = this.getAxis(); | |
| return [axis.coordToData(axis.toLocalCoord( | |
| point[axis.orient === 'horizontal' ? 0 : 1] | |
| ))]; | |
| } | |
| /** | |
| * Convert the series data to concrete point. | |
| * Can be [val] | val | |
| */ | |
| dataToPoint(val: ScaleDataValue | ScaleDataValue[]) { | |
| const axis = this.getAxis(); | |
| const rect = this.getRect(); | |
| const pt = []; | |
| const idx = axis.orient === 'horizontal' ? 0 : 1; | |
| if (val instanceof Array) { | |
| val = val[0]; | |
| } | |
| pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val)); | |
| pt[1 - idx] = idx === 0 ? (rect.y + rect.height / 2) : (rect.x + rect.width / 2); | |
| return pt; | |
| } | |
| convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue[]) { | |
| const coordSys = getCoordSys(finder); | |
| return coordSys === this ? this.dataToPoint(value) : null; | |
| } | |
| convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]) { | |
| const coordSys = getCoordSys(finder); | |
| return coordSys === this ? this.pointToData(pixel) : null; | |
| } | |
| } | |
| function getCoordSys(finder: ParsedModelFinderKnown): Single { | |
| const seriesModel = finder.seriesModel; | |
| const singleModel = finder.singleAxisModel as SingleAxisModel; | |
| return singleModel && singleModel.coordinateSystem | |
| || seriesModel && seriesModel.coordinateSystem as Single; | |
| } | |
| export default Single; |