/* * 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).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;