blob: cee845b8c92f20a45f8c0e626ee5ca61d18cdb9a [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.
*/
/**
* 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';
/**
* Create a single coordinates system.
*/
class Single implements CoordinateSystem, CoordinateSystemMaster {
readonly type = 'single';
readonly dimension = 'single';
/**
* Add it just for draw tooltip.
*/
readonly dimensions = ['single'];
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.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.reverse ? 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;