This is an automated email from the ASF dual-hosted git repository. sushuang pushed a commit to branch typescript in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit a782931bab1c4b4bac2affbdbfbbd582c0451bf0 Author: 100pah <[email protected]> AuthorDate: Sun Mar 1 08:31:15 2020 +0800 Add geo and map series types. And enhance types a bit. --- src/chart/map/MapSeries.ts | 168 ++++++++++++-------- src/chart/map/MapView.ts | 78 ++++++--- src/chart/map/backwardCompat.ts | 11 +- src/chart/map/mapDataStatistic.ts | 21 ++- src/chart/map/mapSymbolLayout.ts | 14 +- src/chart/map/mapVisual.ts | 11 +- src/chart/pie/PieSeries.ts | 16 +- src/component/geo.ts | 14 +- src/component/geo/GeoView.ts | 30 ++-- src/component/helper/MapDraw.ts | 269 +++++++++++++++++--------------- src/component/helper/selectableMixin.ts | 6 +- src/coord/View.ts | 197 +++++++++-------------- src/coord/geo/Geo.ts | 162 ++++++++----------- src/coord/geo/GeoModel.ts | 182 ++++++++++++++------- src/coord/geo/Region.ts | 111 ++++++------- src/coord/geo/fix/diaoyuIsland.ts | 6 +- src/coord/geo/fix/geoCoord.ts | 9 +- src/coord/geo/fix/nanhai.ts | 4 +- src/coord/geo/fix/textCoord.ts | 8 +- src/coord/geo/geoCreator.ts | 70 +++++---- src/coord/geo/geoJSONLoader.ts | 23 +-- src/coord/geo/geoSVGLoader.ts | 33 ++-- src/coord/geo/geoSourceManager.ts | 83 +++++----- src/coord/geo/geoTypes.ts | 116 ++++++++++++++ src/coord/geo/mapDataStorage.ts | 84 +++++----- src/coord/geo/parseGeoJson.ts | 80 +++++----- src/coord/geo/prepareCustom.ts | 9 +- src/echarts.ts | 11 +- src/model/Component.ts | 1 - src/model/Series.ts | 12 +- src/util/graphic.ts | 37 +++-- src/util/types.ts | 20 ++- src/view/Chart.ts | 18 +-- 33 files changed, 1081 insertions(+), 833 deletions(-) diff --git a/src/chart/map/MapSeries.ts b/src/chart/map/MapSeries.ts index a1f4b8c..6b1c8b1 100644 --- a/src/chart/map/MapSeries.ts +++ b/src/chart/map/MapSeries.ts @@ -17,38 +17,100 @@ * under the License. */ -// @ts-nocheck import * as zrUtil from 'zrender/src/core/util'; import createListSimply from '../helper/createListSimply'; import SeriesModel from '../../model/Series'; import {encodeHTML, addCommas} from '../../util/format'; -import {DataSelectableMixin} from '../../component/helper/selectableMixin'; +import {DataSelectableMixin, DataSelectableOptionMixin, SelectableTarget} from '../../component/helper/selectableMixin'; import {retrieveRawAttr} from '../../data/helper/dataProvider'; import geoSourceManager from '../../coord/geo/geoSourceManager'; import {makeSeriesEncodeForNameBased} from '../../data/helper/sourceHelper'; +import { SeriesOption, BoxLayoutOptionMixin, SeriesEncodeOptionMixin, LabelOption, SeriesTooltipOption, OptionDataItemObject, OptionDataValueNumeric, ParsedValue, SeriesOnGeoOptionMixin } from '../../util/types'; +import { Dictionary } from 'zrender/src/core/types'; +import GeoModel, { GeoCommonOptionMixin, GeoItemStyleOption } from '../../coord/geo/GeoModel'; +import List from '../../data/List'; +import Model from '../../model/Model'; +import Geo from '../../coord/geo/Geo'; + +interface MapDataItemOption extends + OptionDataItemObject<OptionDataValueNumeric>, + SelectableTarget { + + itemStyle?: GeoItemStyleOption + label?: LabelOption + + emphasis?: { + itemStyle?: GeoItemStyleOption + label?: LabelOption + } +} -var MapSeries = SeriesModel.extend({ +export type MapValueCalculationType = 'sum' | 'average' | 'min' | 'max'; - type: 'series.map', +export interface MapSeriesOption extends + SeriesOption, + GeoCommonOptionMixin, + // If `geoIndex` is not specified, a exclusive geo will be + // created. Otherwise use the specified geo component, and + // `map` and `mapType` are ignored. + SeriesOnGeoOptionMixin, + BoxLayoutOptionMixin, + DataSelectableOptionMixin, + SeriesEncodeOptionMixin { - dependencies: ['geo'], + coordinateSystem?: string; + silent?: boolean; - layoutMode: 'box', + // FIXME:TS formatter? + label?: LabelOption; + itemStyle?: GeoItemStyleOption; - /** - * Only first map series of same mapType will drawMap - * @type {boolean} - */ - needsDrawMap: false, + tooltip?: SeriesTooltipOption; - /** - * Group of all map series with same mapType - * @type {boolean} - */ - seriesGroup: [], + // FIXME:TS add marker types + markLine?: any; + markPoint?: any; + markArea?: any; + + mapValueCalculation?: MapValueCalculationType; + + showLegendSymbol?: boolean; + + // @deprecated. Only for echarts2 backward compat. + geoCoord?: Dictionary<number[]>; + + data?: OptionDataValueNumeric[] | OptionDataValueNumeric[][] | MapDataItemOption[] + + emphasis?: { + // FIXME:TS formatter? + label?: LabelOption; + itemStyle?: GeoItemStyleOption; + }; +} + +class MapSeries extends SeriesModel<MapSeriesOption> { + + static type = 'series.map' as const; + type = MapSeries.type; + + static dependencies = ['geo']; + + static layoutMode = 'box' as const; + + coordinateSystem: Geo; - getInitialData: function (option) { + // ----------------- + // Injected outside + originalData: List; + mainSeries: MapSeries; + // Only first map series of same mapType will drawMap. + needsDrawMap: boolean = false; + // Group of all map series with same mapType + seriesGroup: MapSeries[] = []; + + + getInitialData(option: MapSeriesOption): List { var data = createListSimply(this, { coordDimensions: ['value'], encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this) @@ -56,7 +118,7 @@ var MapSeries = SeriesModel.extend({ var valueDim = data.mapDimension('value'); var dataNameMap = zrUtil.createHashMap(); var selectTargetList = []; - var toAppendNames = []; + var toAppendNames = [] as string[]; for (var i = 0, len = data.count(); i < len; i++) { var name = data.getName(i); @@ -85,55 +147,51 @@ var MapSeries = SeriesModel.extend({ data.appendValues([], toAppendNames); return data; - }, + } /** * If no host geo model, return null, which means using a * inner exclusive geo model. */ - getHostGeoModel: function () { + getHostGeoModel(): GeoModel { var geoIndex = this.option.geoIndex; return geoIndex != null - ? this.dependentModels.geo[geoIndex] + ? this.dependentModels.geo[geoIndex] as GeoModel : null; - }, + } - getMapType: function () { + getMapType(): string { return (this.getHostGeoModel() || this).option.map; - }, + } - // _fillOption: function (option, mapName) { + // _fillOption(option, mapName) { // Shallow clone // option = zrUtil.extend({}, option); // option.data = geoCreator.getFilledRegions(option.data, mapName, option.nameMap); // return option; - // }, + // } - getRawValue: function (dataIndex) { + getRawValue(dataIndex: number): ParsedValue { // Use value stored in data instead because it is calculated from multiple series // FIXME Provide all value of multiple series ? var data = this.getData(); return data.get(data.mapDimension('value'), dataIndex); - }, + } /** * Get model of region - * @param {string} name - * @return {module:echarts/model/Model} */ - getRegionModel: function (regionName) { + getRegionModel(regionName: string): Model<MapDataItemOption> { var data = this.getData(); return data.getItemModel(data.indexOfName(regionName)); - }, + } /** * Map tooltip formatter - * - * @param {number} dataIndex */ - formatTooltip: function (dataIndex) { + formatTooltip(dataIndex: number): string { // FIXME orignalData and data is a bit confusing var data = this.getData(); var formattedValue = addCommas(this.getRawValue(dataIndex)); @@ -144,7 +202,7 @@ var MapSeries = SeriesModel.extend({ for (var i = 0; i < seriesGroup.length; i++) { var otherIndex = seriesGroup[i].originalData.indexOfName(name); var valueDim = data.mapDimension('value'); - if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) { + if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex) as number)) { seriesNames.push( encodeHTML(seriesGroup[i].name) ); @@ -153,12 +211,9 @@ var MapSeries = SeriesModel.extend({ return seriesNames.join(', ') + '<br />' + encodeHTML(name + ' : ' + formattedValue); - }, + } - /** - * @implement - */ - getTooltipPosition: function (dataIndex) { + getTooltipPosition = function (this: MapSeries, dataIndex: number): number[] { if (dataIndex != null) { var name = this.getData().getName(dataIndex); var geo = this.coordinateSystem; @@ -166,17 +221,17 @@ var MapSeries = SeriesModel.extend({ return region && geo.dataToPoint(region.center); } - }, + }; - setZoom: function (zoom) { + setZoom(zoom: number): void { this.option.zoom = zoom; - }, + } - setCenter: function (center) { + setCenter(center: number[]): void { this.option.center = center; - }, + } - defaultOption: { + static defaultOption: MapSeriesOption = { // 一级层叠 zlevel: 0, // 二级层叠 @@ -211,21 +266,7 @@ var MapSeries = SeriesModel.extend({ // layoutCenter: [50%, 50%] // layoutSize: 100 - - // 数值合并方式,默认加和,可选为: - // 'sum' | 'average' | 'max' | 'min' - // mapValueCalculation: 'sum', - // 地图数值计算结果小数精度 - // mapValuePrecision: 0, - - - // 显示图例颜色标识(系列标识的小圆点),图例开启时有效 showLegendSymbol: true, - // 选择模式,默认关闭,可选single,multiple - // selectedMode: false, - dataRangeHoverLink: true, - // 是否开启缩放及漫游模式 - // roam: false, // Define left-top, right-bottom coords to control view // For example, [ [180, 90], [-180, -90] ], @@ -261,8 +302,9 @@ var MapSeries = SeriesModel.extend({ } } -}); +} -zrUtil.mixin(MapSeries, DataSelectableMixin.prototype); +interface MapSeries extends DataSelectableMixin<MapSeriesOption> {} +zrUtil.mixin(MapSeries, DataSelectableMixin); export default MapSeries; \ No newline at end of file diff --git a/src/chart/map/MapView.ts b/src/chart/map/MapView.ts index d95a6ed..e10ea18 100644 --- a/src/chart/map/MapView.ts +++ b/src/chart/map/MapView.ts @@ -17,21 +17,51 @@ * under the License. */ -// @ts-nocheck -import * as echarts from '../../echarts'; import * as zrUtil from 'zrender/src/core/util'; import * as graphic from '../../util/graphic'; import MapDraw from '../../component/helper/MapDraw'; +import ChartView from '../../view/Chart'; +import MapSeries from './MapSeries'; +import GlobalModel from '../../model/Global'; +import ExtensionAPI from '../../ExtensionAPI'; +import { Payload } from '../../util/types'; +import Model from '../../model/Model'; -var HIGH_DOWN_PROP = '__seriesMapHighDown'; -var RECORD_VERSION_PROP = '__seriesMapCallKey'; -export default echarts.extendChartView({ +var HIGH_DOWN_PROP = '__seriesMapHighDown' as const; +var RECORD_VERSION_PROP = '__seriesMapCallKey' as const; +var ORIGINAL_Z2 = '__mapOriginalZ2' as const; - type: 'map', +interface CircleExtend extends graphic.Circle { + [ORIGINAL_Z2]: number; +} +interface HighDownRecord { + recordVersion: number; + circle: CircleExtend; + labelModel: Model; + hoverLabelModel: Model; + emphasisText: string; + normalText: string; +}; +interface RegionGroupExtend extends graphic.Group { + [HIGH_DOWN_PROP]: HighDownRecord; + [RECORD_VERSION_PROP]: number; +} + +class MapView extends ChartView { + + static type = 'map' as const; + readonly type = MapView.type; + + private _mapDraw: MapDraw; - render: function (mapModel, ecModel, api, payload) { + render( + mapModel: MapSeries, + ecModel: GlobalModel, + api: ExtensionAPI, + payload: Payload + ): void { // Not render if it is an toggleSelect action from self if (payload && payload.type === 'mapToggleSelect' && payload.from === this.uid @@ -73,25 +103,25 @@ export default echarts.extendChartView({ mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') && this._renderSymbols(mapModel, ecModel, api); - }, + } - remove: function () { + remove(): void { this._mapDraw && this._mapDraw.remove(); this._mapDraw = null; this.group.removeAll(); - }, + } - dispose: function () { + dispose(): void { this._mapDraw && this._mapDraw.remove(); this._mapDraw = null; - }, + } - _renderSymbols: function (mapModel, ecModel, api) { + private _renderSymbols(mapModel: MapSeries, ecModel: GlobalModel, api: ExtensionAPI): void { var originalData = mapModel.originalData; var group = this.group; originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) { - if (isNaN(value)) { + if (isNaN(value as number)) { return; } @@ -144,7 +174,7 @@ export default echarts.extendChartView({ var labelModel = itemModel.getModel('label'); var hoverLabelModel = itemModel.getModel('emphasis.label'); - var regionGroup = fullData.getItemGraphicEl(fullIndex); + var regionGroup = fullData.getItemGraphicEl(fullIndex) as RegionGroupExtend; // `getFormattedLabel` needs to use `getData` inside. Here // `mapModel.getData()` is shallow cloned from `mainSeries.getData()`. @@ -167,7 +197,7 @@ export default echarts.extendChartView({ // Prevent from register listeners duplicatedly when roaming. if (!highDownRecord) { - highDownRecord = regionGroup[HIGH_DOWN_PROP] = {}; + highDownRecord = regionGroup[HIGH_DOWN_PROP] = {} as HighDownRecord; var onEmphasis = zrUtil.curry(onRegionHighDown, true); var onNormal = zrUtil.curry(onRegionHighDown, false); regionGroup.on('mouseover', onEmphasis) @@ -195,16 +225,16 @@ export default echarts.extendChartView({ group.add(circle); }); } -}); +} -function onRegionHighDown(toHighOrDown) { +function onRegionHighDown(this: RegionGroupExtend, toHighOrDown: boolean): void { var highDownRecord = this[HIGH_DOWN_PROP]; if (highDownRecord && highDownRecord.recordVersion === this[RECORD_VERSION_PROP]) { enterRegionHighDown(highDownRecord, toHighOrDown); } } -function enterRegionHighDown(highDownRecord, toHighOrDown) { +function enterRegionHighDown(highDownRecord: HighDownRecord, toHighOrDown: boolean): void { var circle = highDownRecord.circle; var labelModel = highDownRecord.labelModel; var hoverLabelModel = highDownRecord.hoverLabelModel; @@ -218,7 +248,7 @@ function enterRegionHighDown(highDownRecord, toHighOrDown) { }, {isRectText: true, useInsideStyle: false}, true) ); // Make label upper than others if overlaps. - circle.__mapOriginalZ2 = circle.z2; + circle[ORIGINAL_Z2] = circle.z2; circle.z2 += graphic.Z2_EMPHASIS_LIFT; } else { @@ -229,9 +259,11 @@ function enterRegionHighDown(highDownRecord, toHighOrDown) { // Trigger normalize style like padding. circle.dirty(false); - if (circle.__mapOriginalZ2 != null) { - circle.z2 = circle.__mapOriginalZ2; - circle.__mapOriginalZ2 = null; + if (circle[ORIGINAL_Z2] != null) { + circle.z2 = circle[ORIGINAL_Z2]; + circle[ORIGINAL_Z2] = null; } } } + +export default MapView; diff --git a/src/chart/map/backwardCompat.ts b/src/chart/map/backwardCompat.ts index d401323..1c450a0 100644 --- a/src/chart/map/backwardCompat.ts +++ b/src/chart/map/backwardCompat.ts @@ -17,19 +17,18 @@ * under the License. */ -// @ts-nocheck - import * as zrUtil from 'zrender/src/core/util'; +import { ECUnitOption, SeriesOption } from '../../util/types'; -export default function (option) { +export default function (option: ECUnitOption) { // Save geoCoord var mapSeries = []; - zrUtil.each(option.series, function (seriesOpt) { + zrUtil.each(option.series, function (seriesOpt: SeriesOption) { if (seriesOpt && seriesOpt.type === 'map') { mapSeries.push(seriesOpt); - seriesOpt.map = seriesOpt.map || seriesOpt.mapType; + (seriesOpt as any).map = (seriesOpt as any).map || (seriesOpt as any).mapType; // Put x, y, width, height, x2, y2 in the top level - zrUtil.defaults(seriesOpt, seriesOpt.mapLocation); + zrUtil.defaults(seriesOpt, (seriesOpt as any).mapLocation); } }); } \ No newline at end of file diff --git a/src/chart/map/mapDataStatistic.ts b/src/chart/map/mapDataStatistic.ts index 4825c17..adb36b5 100644 --- a/src/chart/map/mapDataStatistic.ts +++ b/src/chart/map/mapDataStatistic.ts @@ -17,21 +17,18 @@ * under the License. */ -// @ts-nocheck import * as zrUtil from 'zrender/src/core/util'; +import List from '../../data/List'; +import MapSeries, { MapValueCalculationType } from './MapSeries'; +import GlobalModel from '../../model/Global'; // FIXME 公用? -/** - * @param {Array.<module:echarts/data/List>} datas - * @param {string} statisticType 'average' 'sum' - * @inner - */ -function dataStatistics(datas, statisticType) { - var dataNameMap = {}; +function dataStatistics(datas: List[], statisticType: MapValueCalculationType): List { + var dataNameMap = {} as {[mapKey: string]: number[]}; zrUtil.each(datas, function (data) { - data.each(data.mapDimension('value'), function (value, idx) { + data.each(data.mapDimension('value'), function (value: number, idx) { // Add prefix to avoid conflict with Object.prototype. var mapKey = 'ec-' + data.getName(idx); dataNameMap[mapKey] = dataNameMap[mapKey] || []; @@ -69,9 +66,9 @@ function dataStatistics(datas, statisticType) { }); } -export default function (ecModel) { - var seriesGroups = {}; - ecModel.eachSeriesByType('map', function (seriesModel) { +export default function (ecModel: GlobalModel): void { + var seriesGroups = {} as {[key: string]: MapSeries[]}; + ecModel.eachSeriesByType('map', function (seriesModel: MapSeries) { var hostGeoModel = seriesModel.getHostGeoModel(); var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType(); (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel); diff --git a/src/chart/map/mapSymbolLayout.ts b/src/chart/map/mapSymbolLayout.ts index 93d28b8..b3a4475 100644 --- a/src/chart/map/mapSymbolLayout.ts +++ b/src/chart/map/mapSymbolLayout.ts @@ -17,21 +17,23 @@ * under the License. */ -// @ts-nocheck import * as zrUtil from 'zrender/src/core/util'; +import GlobalModel from '../../model/Global'; +import MapSeries from './MapSeries'; +import { Dictionary } from '../../util/types'; -export default function (ecModel) { +export default function (ecModel: GlobalModel) { - var processedMapType = {}; + var processedMapType = {} as {[mapType: string]: boolean}; - ecModel.eachSeriesByType('map', function (mapSeries) { + ecModel.eachSeriesByType('map', function (mapSeries: MapSeries) { var mapType = mapSeries.getMapType(); if (mapSeries.getHostGeoModel() || processedMapType[mapType]) { return; } - var mapSymbolOffsets = {}; + var mapSymbolOffsets = {} as Dictionary<number>; zrUtil.each(mapSeries.seriesGroup, function (subMapSeries) { var geo = subMapSeries.coordinateSystem; @@ -44,7 +46,7 @@ export default function (ecModel) { // If input series.data is [11, 22, '-'/null/undefined, 44], // it will be filled with NaN: [11, 22, NaN, 44] and NaN will // not be drawn. So here must validate if value is NaN. - if (!region || isNaN(value)) { + if (!region || isNaN(value as number)) { return; } diff --git a/src/chart/map/mapVisual.ts b/src/chart/map/mapVisual.ts index f841bf8..617f729 100644 --- a/src/chart/map/mapVisual.ts +++ b/src/chart/map/mapVisual.ts @@ -1,3 +1,7 @@ +import GlobalModel from '../../model/Global'; +import MapSeries from './MapSeries'; +import { ZRColor } from '../../util/types'; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,11 +21,10 @@ * under the License. */ -// @ts-nocheck -export default function (ecModel) { - ecModel.eachSeriesByType('map', function (seriesModel) { - var colorList = seriesModel.get('color'); +export default function (ecModel: GlobalModel) { + ecModel.eachSeriesByType('map', function (seriesModel: MapSeries) { + var colorList = seriesModel.get('color') as ZRColor[]; var itemStyleModel = seriesModel.getModel('itemStyle'); var areaColor = itemStyleModel.get('areaColor'); diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts index d3cb9d0..9a51351 100644 --- a/src/chart/pie/PieSeries.ts +++ b/src/chart/pie/PieSeries.ts @@ -34,7 +34,9 @@ import { ItemStyleOption, LabelOption, BoxLayoutOptionMixin, - OptionDataValueNumeric + OptionDataValueNumeric, + SeriesEncodeOptionMixin, + OptionDataItemObject } from '../../util/types'; import List from '../../data/List'; @@ -46,10 +48,9 @@ interface PieLabelOption extends LabelOption { distanceToLabelLine?: number } -interface PieDataItem { - name?: string - - value?: OptionDataValueNumeric +interface PieDataItem extends + OptionDataItemObject<OptionDataValueNumeric>, + SelectableTarget { itemStyle?: ItemStyleOption label?: PieLabelOption @@ -65,7 +66,8 @@ export interface PieSeriesOption extends SeriesOption, DataSelectableOptionMixin, CircleLayoutOptionMixin, - BoxLayoutOptionMixin { + BoxLayoutOptionMixin, + SeriesEncodeOptionMixin { type: 'pie' @@ -100,7 +102,7 @@ export interface PieSeriesOption extends animationType?: 'expansion' | 'scale' animationTypeUpdate?: 'transition' | 'expansion' - data?: OptionDataValueNumeric[] | PieDataItem[] + data?: OptionDataValueNumeric[] | OptionDataValueNumeric[][] | PieDataItem[] } class PieSeriesModel extends SeriesModel<PieSeriesOption> { diff --git a/src/component/geo.ts b/src/component/geo.ts index d949f7e..d6e4bc5 100644 --- a/src/component/geo.ts +++ b/src/component/geo.ts @@ -17,7 +17,6 @@ * under the License. */ -// @ts-nocheck import * as echarts from '../echarts'; import * as zrUtil from 'zrender/src/core/util'; @@ -26,15 +25,20 @@ import '../coord/geo/GeoModel'; import '../coord/geo/geoCreator'; import './geo/GeoView'; import '../action/geoRoam'; +import { ActionInfo } from '../util/types'; +import GeoModel from '../coord/geo/GeoModel'; -function makeAction(method, actionInfo) { +function makeAction( + method: 'toggleSelected' | 'select' | 'unSelect', + actionInfo: ActionInfo +): void { actionInfo.update = 'updateView'; echarts.registerAction(actionInfo, function (payload, ecModel) { - var selected = {}; + var selected = {} as {[regionName: string]: boolean}; ecModel.eachComponent( { mainType: 'geo', query: payload}, - function (geoModel) { + function (geoModel: GeoModel) { geoModel[method](payload.name); var geo = geoModel.coordinateSystem; zrUtil.each(geo.regions, function (region) { @@ -61,4 +65,4 @@ makeAction('select', { makeAction('unSelect', { type: 'geoUnSelect', event: 'geounselected' -}); \ No newline at end of file +}); diff --git a/src/component/geo/GeoView.ts b/src/component/geo/GeoView.ts index f132e20..e8b32b7 100644 --- a/src/component/geo/GeoView.ts +++ b/src/component/geo/GeoView.ts @@ -17,23 +17,31 @@ * under the License. */ -// @ts-nocheck import MapDraw from '../helper/MapDraw'; -import * as echarts from '../../echarts'; +import ComponentView from '../../view/Component'; +import GlobalModel from '../../model/Global'; +import ExtensionAPI from '../../ExtensionAPI'; +import GeoModel from '../../coord/geo/GeoModel'; +import { Payload } from '../../util/types'; -export default echarts.extendComponentView({ +class GeoView extends ComponentView { - type: 'geo', + static type = 'geo' as const; + readonly type = GeoView.type; - init: function (ecModel, api) { + private _mapDraw: MapDraw; + + init(ecModel: GlobalModel, api: ExtensionAPI) { var mapDraw = new MapDraw(api, true); this._mapDraw = mapDraw; this.group.add(mapDraw.group); - }, + } - render: function (geoModel, ecModel, api, payload) { + render( + geoModel: GeoModel, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload + ): void { // Not render if it is an toggleSelect action from self if (payload && payload.type === 'geoToggleSelect' && payload.from === this.uid @@ -50,10 +58,12 @@ export default echarts.extendComponentView({ } this.group.silent = geoModel.get('silent'); - }, + } - dispose: function () { + dispose(): void { this._mapDraw && this._mapDraw.remove(); } -}); \ No newline at end of file +} + +export default GeoView; diff --git a/src/component/helper/MapDraw.ts b/src/component/helper/MapDraw.ts index a418341..46eebb1 100644 --- a/src/component/helper/MapDraw.ts +++ b/src/component/helper/MapDraw.ts @@ -17,8 +17,6 @@ * under the License. */ -// @ts-nocheck - import * as zrUtil from 'zrender/src/core/util'; import RoamController from './RoamController'; import * as roamHelper from '../../component/helper/roamHelper'; @@ -26,8 +24,25 @@ import {onIrrelevantElement} from '../../component/helper/cursorHelper'; import * as graphic from '../../util/graphic'; import geoSourceManager from '../../coord/geo/geoSourceManager'; import {getUID} from '../../util/component'; +import ExtensionAPI from '../../ExtensionAPI'; +import GeoModel, { GeoCommonOptionMixin, GeoItemStyleOption } from '../../coord/geo/GeoModel'; +import MapSeries from '../../chart/map/MapSeries'; +import GlobalModel from '../../model/Global'; +import { Payload, ECElement } from '../../util/types'; +import GeoView from '../geo/GeoView'; +import MapView from '../../chart/map/MapView'; +import ComponentModel from '../../model/Component'; +import Region from '../../coord/geo/Region'; +import Element from 'zrender/src/Element'; +import Geo from '../../coord/geo/Geo'; +import Model from '../../model/Model'; + + +interface RegionsGroup extends graphic.Group { + __regions: Region[]; +} -function getFixedItemStyle(model) { +function getFixedItemStyle(model: Model<GeoItemStyleOption>) { var itemStyle = model.getItemStyle(); var areaColor = model.get('areaColor'); @@ -40,137 +55,74 @@ function getFixedItemStyle(model) { return itemStyle; } -function updateMapSelectHandler(mapDraw, mapOrGeoModel, regionsGroup, api, fromView) { - regionsGroup.off('click'); - regionsGroup.off('mousedown'); - - if (mapOrGeoModel.get('selectedMode')) { - - regionsGroup.on('mousedown', function () { - mapDraw._mouseDownFlag = true; - }); - - regionsGroup.on('click', function (e) { - if (!mapDraw._mouseDownFlag) { - return; - } - mapDraw._mouseDownFlag = false; - - var el = e.target; - while (!el.__regions) { - el = el.parent; - } - if (!el) { - return; - } - - var action = { - type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect', - batch: zrUtil.map(el.__regions, function (region) { - return { - name: region.name, - from: fromView.uid - }; - }) - }; - action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id; - - api.dispatchAction(action); - - updateMapSelected(mapOrGeoModel, regionsGroup); - }); - } -} - -function updateMapSelected(mapOrGeoModel, regionsGroup) { +function updateMapSelected(mapOrGeoModel: GeoModel | MapSeries, regionsGroup: RegionsGroup) { // FIXME regionsGroup.eachChild(function (otherRegionEl) { - zrUtil.each(otherRegionEl.__regions, function (region) { + zrUtil.each((otherRegionEl as RegionsGroup).__regions, function (region) { otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal'); }); }); } -/** - * @alias module:echarts/component/helper/MapDraw - * @param {module:echarts/ExtensionAPI} api - * @param {boolean} updateGroup - */ -function MapDraw(api, updateGroup) { - - var group = new graphic.Group(); +class MapDraw { - /** - * @type {string} - * @private - */ - this.uid = getUID('ec_map_draw'); + private uid: string; - /** - * @type {module:echarts/component/helper/RoamController} - * @private - */ - this._controller = new RoamController(api.getZr()); + // @ts-ignore FIXME:TS + private _controller: RoamController; - /** - * @type {Object} {target, zoom, zoomLimit} - * @private - */ - this._controllerHost = {target: updateGroup ? group : null}; + private _controllerHost: { + target?: graphic.Group; + zoom?: number; + zoomLimit?: GeoCommonOptionMixin['scaleLimit']; + }; - /** - * @type {module:zrender/container/Group} - * @readOnly - */ - this.group = group; + readonly group: graphic.Group; - /** - * @type {boolean} - * @private - */ - this._updateGroup = updateGroup; + private _updateGroup: boolean; /** * This flag is used to make sure that only one among * `pan`, `zoom`, `click` can occurs, otherwise 'selected' * action may be triggered when `pan`, which is unexpected. - * @type {booelan} */ - this._mouseDownFlag; + private _mouseDownFlag: boolean; - /** - * @type {string} - */ - this._mapName; + private _mapName: string; - /** - * @type {boolean} - */ - this._initialized; + private _initialized: string; - /** - * @type {module:zrender/container/Group} - */ - group.add(this._regionsGroup = new graphic.Group()); + private _regionsGroup: RegionsGroup; + + private _backgroundGroup: graphic.Group; - /** - * @type {module:zrender/container/Group} - */ - group.add(this._backgroundGroup = new graphic.Group()); -} -MapDraw.prototype = { + constructor(api: ExtensionAPI, updateGroup: boolean) { + var group = new graphic.Group(); + this.uid = getUID('ec_map_draw'); + // @ts-ignore FIXME:TS + this._controller = new RoamController(api.getZr()); + this._controllerHost = {target: updateGroup ? group : null}; + this.group = group; + this._updateGroup = updateGroup; - constructor: MapDraw, + group.add(this._regionsGroup = new graphic.Group() as RegionsGroup); + group.add(this._backgroundGroup = new graphic.Group()); + } - draw: function (mapOrGeoModel, ecModel, api, fromView, payload) { + draw( + mapOrGeoModel: GeoModel | MapSeries, + ecModel: GlobalModel, + api: ExtensionAPI, + fromView: MapView | GeoView + ): void { var isGeo = mapOrGeoModel.mainType === 'geo'; // Map series has data. GEO model that controlled by map series // will be assigned with map data. Other GEO model has no data. - var data = mapOrGeoModel.getData && mapOrGeoModel.getData(); - isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries) { + var data = (mapOrGeoModel as MapSeries).getData && (mapOrGeoModel as MapSeries).getData(); + isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries: MapSeries) { if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) { data = mapSeries.getData(); } @@ -193,11 +145,11 @@ MapDraw.prototype = { regionsGroup.removeAll(); - var itemStyleAccessPath = ['itemStyle']; - var hoverItemStyleAccessPath = ['emphasis', 'itemStyle']; - var labelAccessPath = ['label']; - var hoverLabelAccessPath = ['emphasis', 'label']; - var nameMap = zrUtil.createHashMap(); + var itemStyleAccessPath = ['itemStyle'] as const; + var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'] as const; + var labelAccessPath = ['label'] as const; + var hoverLabelAccessPath = ['emphasis', 'label'] as const; + var nameMap = zrUtil.createHashMap<RegionsGroup>(); zrUtil.each(geo.regions, function (region) { // Consider in GeoJson properties.name may be duplicated, for example, @@ -206,7 +158,7 @@ MapDraw.prototype = { // will make them share the same label and bring trouble in label // location calculation. var regionGroup = nameMap.get(region.name) - || nameMap.set(region.name, new graphic.Group()); + || nameMap.set(region.name, new graphic.Group() as RegionsGroup); var compoundPath = new graphic.CompoundPath({ segmentIgnoreThreshold: 1, @@ -216,14 +168,18 @@ MapDraw.prototype = { }); regionGroup.add(compoundPath); - var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel; + const regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel; + // @ts-ignore FIXME:TS fix the "compatible with each other"? var itemStyleModel = regionModel.getModel(itemStyleAccessPath); + // @ts-ignore FIXME:TS fix the "compatible with each other"? var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath); var itemStyle = getFixedItemStyle(itemStyleModel); var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel); + // @ts-ignore FIXME:TS fix the "compatible with each other"? var labelModel = regionModel.getModel(labelAccessPath); + // @ts-ignore FIXME:TS fix the "compatible with each other"? var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath); var dataIdx; @@ -240,7 +196,7 @@ MapDraw.prototype = { } } - var transformPoint = function (point) { + var transformPoint = function (point: number[]): number[] { return [ point[0] * scale[0] + position[0], point[1] * scale[1] + position[1] @@ -285,7 +241,7 @@ MapDraw.prototype = { var showLabel = labelModel.get('show'); var hoverShowLabel = hoverLabelModel.get('show'); - var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx)); + var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx) as number); var itemLayout = data && data.getItemLayout(dataIdx); // In the following cases label will be drawn // 1. In map series and data value is NaN @@ -314,7 +270,7 @@ MapDraw.prototype = { silent: true }); - graphic.setLabelStyle( + graphic.setLabelStyle<typeof query>( textEl.style, textEl.hoverStyle = {}, labelModel, hoverLabelModel, { labelFetcher: labelFetcher, @@ -337,9 +293,9 @@ MapDraw.prototype = { data.setItemGraphicEl(dataIdx, regionGroup); } else { - var regionModel = mapOrGeoModel.getRegionModel(region.name); + const regionModel = mapOrGeoModel.getRegionModel(region.name); // Package custom mouse event for geo component - compoundPath.eventData = { + (compoundPath as Element as ECElement).eventData = { componentType: 'geo', componentIndex: mapOrGeoModel.componentIndex, geoIndex: mapOrGeoModel.componentIndex, @@ -351,6 +307,7 @@ MapDraw.prototype = { var groupRegions = regionGroup.__regions || (regionGroup.__regions = []); groupRegions.push(region); + // @ts-ignore FIXME:TS fix the "compatible with each other"? regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode'); graphic.setHoverStyle(regionGroup, hoverItemStyle); @@ -359,21 +316,21 @@ MapDraw.prototype = { this._updateController(mapOrGeoModel, ecModel, api); - updateMapSelectHandler(this, mapOrGeoModel, regionsGroup, api, fromView); + this._updateMapSelectHandler(mapOrGeoModel, regionsGroup, api, fromView); updateMapSelected(mapOrGeoModel, regionsGroup); - }, + } - remove: function () { + remove(): void { this._regionsGroup.removeAll(); this._backgroundGroup.removeAll(); this._controller.dispose(); this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid); this._mapName = null; this._controllerHost = {}; - }, + } - _updateBackground: function (geo) { + private _updateBackground(geo: Geo): void { var mapName = geo.map; if (this._mapName !== mapName) { @@ -383,30 +340,35 @@ MapDraw.prototype = { } this._mapName = mapName; - }, + } - _updateController: function (mapOrGeoModel, ecModel, api) { + private _updateController( + mapOrGeoModel: GeoModel | MapSeries, ecModel: GlobalModel, api: ExtensionAPI + ): void { var geo = mapOrGeoModel.coordinateSystem; var controller = this._controller; var controllerHost = this._controllerHost; + // @ts-ignore FIXME:TS controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit'); controllerHost.zoom = geo.getZoom(); // roamType is will be set default true if it is null + // @ts-ignore FIXME:TS controller.enable(mapOrGeoModel.get('roam') || false); var mainType = mapOrGeoModel.mainType; - function makeActionBase() { + function makeActionBase(): Payload { var action = { type: 'geoRoam', componentType: mainType - }; + } as Payload; action[mainType + 'Id'] = mapOrGeoModel.id; return action; } - controller.off('pan').on('pan', function (e) { + // @ts-ignore FIXME:TS + controller.off('pan').on('pan', function (this: MapDraw, e) { this._mouseDownFlag = false; roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy); @@ -417,7 +379,8 @@ MapDraw.prototype = { })); }, this); - controller.off('zoom').on('zoom', function (e) { + // @ts-ignore FIXME:TS + controller.off('zoom').on('zoom', function (this: MapDraw, e) { this._mouseDownFlag = false; roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); @@ -438,11 +401,63 @@ MapDraw.prototype = { } }, this); + // @ts-ignore FIXME:TS controller.setPointerChecker(function (e, x, y) { return geo.getViewRectAfterRoam().contain(x, y) && !onIrrelevantElement(e, api, mapOrGeoModel); }); } + + private _updateMapSelectHandler( + mapOrGeoModel: GeoModel | MapSeries, + regionsGroup: RegionsGroup, + api: ExtensionAPI, + fromView: MapView | GeoView + ): void { + var mapDraw = this; + + regionsGroup.off('click'); + regionsGroup.off('mousedown'); + + // @ts-ignore FIXME:TS resolve type conflict + if (mapOrGeoModel.get('selectedMode')) { + + regionsGroup.on('mousedown', function () { + mapDraw._mouseDownFlag = true; + }); + + regionsGroup.on('click', function (e) { + if (!mapDraw._mouseDownFlag) { + return; + } + mapDraw._mouseDownFlag = false; + + var el = e.target; + while (!(el as RegionsGroup).__regions) { + el = el.parent; + } + if (!el) { + return; + } + + var action = { + type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect', + batch: zrUtil.map((el as RegionsGroup).__regions, function (region) { + return { + name: region.name, + from: fromView.uid + }; + }) + } as Payload; + action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id; + + api.dispatchAction(action); + + updateMapSelected(mapOrGeoModel, regionsGroup); + }); + } + } + }; export default MapDraw; diff --git a/src/component/helper/selectableMixin.ts b/src/component/helper/selectableMixin.ts index c45db1e..afc2415 100644 --- a/src/component/helper/selectableMixin.ts +++ b/src/component/helper/selectableMixin.ts @@ -28,9 +28,9 @@ import Model from '../../model/Model'; import { Dictionary } from 'zrender/src/core/types'; export interface SelectableTarget { - name: string, - value: any, - selected: boolean + name?: string; + selected?: boolean; + [key: string]: any; }; export interface DataSelectableOptionMixin { diff --git a/src/coord/View.ts b/src/coord/View.ts index be65472..ebf0e42 100644 --- a/src/coord/View.ts +++ b/src/coord/View.ts @@ -17,8 +17,6 @@ * under the License. */ -// @ts-nocheck - /** * Simple view coordinate system * Mapping given x, y to transformd view x, y @@ -29,89 +27,64 @@ import * as vector from 'zrender/src/core/vector'; import * as matrix from 'zrender/src/core/matrix'; import BoundingRect from 'zrender/src/core/BoundingRect'; import Transformable from 'zrender/src/core/Transformable'; +import { CoordinateSystemMaster, CoordinateSystem } from './CoordinateSystem'; +import GlobalModel from '../model/Global'; +import { ParsedModelFinder } from '../util/model'; var v2ApplyTransform = vector.applyTransform; -// Dummy transform node -function TransformDummy() { - Transformable.call(this); -} -zrUtil.mixin(TransformDummy, Transformable); +class View extends Transformable implements CoordinateSystemMaster, CoordinateSystem { -function View(name) { - /** - * @type {string} - */ - this.name = name; + readonly type: string = 'view'; - /** - * @type {Object} - */ - this.zoomLimit; + static dimensions = ['x', 'y']; + readonly dimensions = ['x', 'y']; - Transformable.call(this); + readonly name: string; - this._roamTransformable = new TransformDummy(); + zoomLimit: { + max?: number; + min?: number; + }; - this._rawTransformable = new TransformDummy(); + private _roamTransformable = new Transformable(); + protected _rawTransformable = new Transformable(); - this._center; - this._zoom; -} + private _center: number[]; + private _zoom: number; + protected _rect: BoundingRect; + private _viewRect: BoundingRect; + private _rawTransform: matrix.MatrixArray; -View.prototype = { - constructor: View, - - type: 'view', - - /** - * @param {Array.<string>} - * @readOnly - */ - dimensions: ['x', 'y'], - - /** - * Set bounding rect - * @param {number} x - * @param {number} y - * @param {number} width - * @param {number} height - */ + constructor(name: string) { + super(); + this.name = name; + } // PENDING to getRect - setBoundingRect: function (x, y, width, height) { + setBoundingRect(x: number, y: number, width: number, height: number): BoundingRect { this._rect = new BoundingRect(x, y, width, height); return this._rect; - }, + } /** * @return {module:zrender/core/BoundingRect} */ // PENDING to getRect - getBoundingRect: function () { + getBoundingRect(): BoundingRect { return this._rect; - }, + } - /** - * @param {number} x - * @param {number} y - * @param {number} width - * @param {number} height - */ - setViewRect: function (x, y, width, height) { + setViewRect(x: number, y: number, width: number, height: number): void { this.transformTo(x, y, width, height); this._viewRect = new BoundingRect(x, y, width, height); - }, + } /** * Transformed to particular position and size - * @param {number} x - * @param {number} y - * @param {number} width - * @param {number} height */ - transformTo: function (x, y, width, height) { + transformTo(x: number, y: number, width: number, height: number): void { var rect = this.getBoundingRect(); var rawTransform = this._rawTransformable; @@ -122,25 +95,21 @@ View.prototype = { rawTransform.decomposeTransform(); this._updateTransform(); - }, + } /** * Set center of view - * @param {Array.<number>} [centerCoord] */ - setCenter: function (centerCoord) { + setCenter(centerCoord?: number[]): void { if (!centerCoord) { return; } this._center = centerCoord; this._updateCenterAndZoom(); - }, + } - /** - * @param {number} zoom - */ - setZoom: function (zoom) { + setZoom(zoom: number): void { zoom = zoom || 1; var zoomLimit = this.zoomLimit; @@ -155,39 +124,36 @@ View.prototype = { this._zoom = zoom; this._updateCenterAndZoom(); - }, + } /** * Get default center without roam */ - getDefaultCenter: function () { + getDefaultCenter(): number[] { // Rect before any transform var rawRect = this.getBoundingRect(); var cx = rawRect.x + rawRect.width / 2; var cy = rawRect.y + rawRect.height / 2; return [cx, cy]; - }, + } - getCenter: function () { + getCenter(): number[] { return this._center || this.getDefaultCenter(); - }, + } - getZoom: function () { + getZoom(): number { return this._zoom || 1; - }, + } - /** - * @return {Array.<number} - */ - getRoamTransform: function () { + getRoamTransform(): matrix.MatrixArray { return this._roamTransformable.getLocalTransform(); - }, + } /** * Remove roam */ - _updateCenterAndZoom: function () { + private _updateCenterAndZoom(): void { // Must update after view transform updated var rawTransformMatrix = this._rawTransformable.getLocalTransform(); var roamTransform = this._roamTransformable; @@ -206,13 +172,12 @@ View.prototype = { roamTransform.scale = [zoom, zoom]; this._updateTransform(); - }, + } /** * Update transform from roam and mapLocation - * @private */ - _updateTransform: function () { + protected _updateTransform(): void { var roamTransformable = this._roamTransformable; var rawTransformable = this._rawTransformable; @@ -228,9 +193,13 @@ View.prototype = { matrix.invert(this.invTransform, this.transform); this.decomposeTransform(); - }, + } - getTransformInfo: function () { + getTransformInfo(): { + roamTransform: matrix.MatrixArray, + rawScale: number[], + rawPosition: number[] + } { var roamTransform = this._roamTransformable.transform; var rawTransformable = this._rawTransformable; return { @@ -238,89 +207,73 @@ View.prototype = { rawScale: zrUtil.slice(rawTransformable.scale), rawPosition: zrUtil.slice(rawTransformable.position) }; - }, + } - /** - * @return {module:zrender/core/BoundingRect} - */ - getViewRect: function () { + getViewRect(): BoundingRect { return this._viewRect; - }, + } /** * Get view rect after roam transform - * @return {module:zrender/core/BoundingRect} */ - getViewRectAfterRoam: function () { + getViewRectAfterRoam(): BoundingRect { var rect = this.getBoundingRect().clone(); rect.applyTransform(this.transform); return rect; - }, + } /** * Convert a single (lon, lat) data item to (x, y) point. - * @param {Array.<number>} data - * @param {boolean} noRoam - * @param {Array.<number>} [out] - * @return {Array.<number>} */ - dataToPoint: function (data, noRoam, out) { + dataToPoint(data: number[], noRoam?: boolean, out?: number[]): number[] { var transform = noRoam ? this._rawTransform : this.transform; out = out || []; return transform ? v2ApplyTransform(out, data, transform) : vector.copy(out, data); - }, + } /** * Convert a (x, y) point to (lon, lat) data - * @param {Array.<number>} point - * @return {Array.<number>} */ - pointToData: function (point) { + pointToData(point: number[]): number[] { var invTransform = this.invTransform; return invTransform ? v2ApplyTransform([], point, invTransform) : [point[0], point[1]]; - }, + } - /** - * @implements - * see {module:echarts/CoodinateSystem} - */ - convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'), + convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: number[]): number[] { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + } - /** - * @implements - * see {module:echarts/CoodinateSystem} - */ - convertFromPixel: zrUtil.curry(doConvert, 'pointToData'), + convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]): number[] { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + } /** * @implements - * see {module:echarts/CoodinateSystem} */ - containPoint: function (point) { + containPoint(point: number[]): boolean { return this.getViewRectAfterRoam().contain(point[0], point[1]); } /** * @return {number} */ - // getScalarScale: function () { + // getScalarScale() { // // Use determinant square root of transform to mutiply scalar // var m = this.transform; // var det = Math.sqrt(Math.abs(m[0] * m[3] - m[2] * m[1])); // return det; // } -}; - -zrUtil.mixin(View, Transformable); +} -function doConvert(methodName, ecModel, finder, value) { +function getCoordSys(finder: ParsedModelFinder): View { var seriesModel = finder.seriesModel; - var coordSys = seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph. - return coordSys === this ? coordSys[methodName](value) : null; + return seriesModel ? seriesModel.coordinateSystem as View : null; // e.g., graph. } -export default View; \ No newline at end of file +export default View; diff --git a/src/coord/geo/Geo.ts b/src/coord/geo/Geo.ts index 6cf370f..90f8076 100644 --- a/src/coord/geo/Geo.ts +++ b/src/coord/geo/Geo.ts @@ -17,71 +17,62 @@ * under the License. */ -// @ts-nocheck - import * as zrUtil from 'zrender/src/core/util'; import BoundingRect from 'zrender/src/core/BoundingRect'; import View from '../View'; import geoSourceManager from './geoSourceManager'; +import Region from './Region'; +import { NameMap } from './geoTypes'; +import GlobalModel from '../../model/Global'; +import { ParsedModelFinder } from '../../util/model'; +import GeoModel from './GeoModel'; +import { resizeGeoType } from './geoCreator'; -/** - * [Geo description] - * For backward compatibility, the orginal interface: - * `name, map, geoJson, specialAreas, nameMap` is kept. - * - * @param {string|Object} name - * @param {string} map Map type - * Specify the positioned areas by left, top, width, height - * @param {Object.<string, string>} [nameMap] - * Specify name alias - * @param {boolean} [invertLongitute=true] - */ -function Geo(name, map, nameMap, invertLongitute) { +class Geo extends View { - View.call(this, name); + dimensions = ['lng', 'lat']; - /** - * Map type - * @type {string} - */ - this.map = map; + type = 'geo'; - var source = geoSourceManager.load(map, nameMap); + // map type + readonly map: string; - this._nameCoordMap = source.nameCoordMap; - this._regionsMap = source.regionsMap; - this._invertLongitute = invertLongitute == null ? true : invertLongitute; + private _nameCoordMap: zrUtil.HashMap<number[]>; + private _regionsMap: zrUtil.HashMap<Region>; + private _invertLongitute: boolean; + readonly regions: Region[]; - /** - * @readOnly - */ - this.regions = source.regions; + // Injected outside + aspectScale: number; + model: GeoModel; + resize: resizeGeoType; /** - * @type {module:zrender/src/core/BoundingRect} + * For backward compatibility, the orginal interface: + * `name, map, geoJson, specialAreas, nameMap` is kept. + * + * @param map Map type Specify the positioned areas by left, top, width, height. + * @param [nameMap] Specify name alias */ - this._rect = source.boundingRect; -} + constructor(name: string, map: string, nameMap?: NameMap, invertLongitute?: boolean) { + super(name); -Geo.prototype = { + this.map = map; - constructor: Geo, + var source = geoSourceManager.load(map, nameMap); - type: 'geo', + this._nameCoordMap = source.nameCoordMap; + this._regionsMap = source.regionsMap; + this._invertLongitute = invertLongitute == null ? true : invertLongitute; + this.regions = source.regions; + this._rect = source.boundingRect; + } /** - * @param {Array.<string>} - * @readOnly + * Whether contain the given [lng, lat] coord. */ - dimensions: ['lng', 'lat'], - - /** - * If contain given lng,lat coord - * @param {Array.<number>} - * @readOnly - */ - containCoord: function (coord) { + containCoord(coord: number[]) { var regions = this.regions; for (var i = 0; i < regions.length; i++) { if (regions[i].contain(coord)) { @@ -89,12 +80,9 @@ Geo.prototype = { } } return false; - }, + } - /** - * @override - */ - transformTo: function (x, y, width, height) { + transformTo(x: number, y: number, width: number, height: number): void { var rect = this.getBoundingRect(); var invertLongitute = this._invertLongitute; @@ -121,57 +109,40 @@ Geo.prototype = { rawTransformable.updateTransform(); this._updateTransform(); - }, + } - /** - * @param {string} name - * @return {module:echarts/coord/geo/Region} - */ - getRegion: function (name) { + getRegion(name: string): Region { return this._regionsMap.get(name); - }, + } - getRegionByCoord: function (coord) { + getRegionByCoord(coord: number[]): Region { var regions = this.regions; for (var i = 0; i < regions.length; i++) { if (regions[i].contain(coord)) { return regions[i]; } } - }, + } /** * Add geoCoord for indexing by name - * @param {string} name - * @param {Array.<number>} geoCoord */ - addGeoCoord: function (name, geoCoord) { + addGeoCoord(name: string, geoCoord: number[]): void { this._nameCoordMap.set(name, geoCoord); - }, + } /** * Get geoCoord by name - * @param {string} name - * @return {Array.<number>} */ - getGeoCoord: function (name) { + getGeoCoord(name: string): number[] { return this._nameCoordMap.get(name); - }, + } - /** - * @override - */ - getBoundingRect: function () { + getBoundingRect(): BoundingRect { return this._rect; - }, + } - /** - * @param {string|Array.<number>} data - * @param {boolean} noRoam - * @param {Array.<number>} [out] - * @return {Array.<number>} - */ - dataToPoint: function (data, noRoam, out) { + dataToPoint(data: number[], noRoam?: boolean, out?: number[]): number[] { if (typeof data === 'string') { // Map area name to geoCoord data = this.getGeoCoord(data); @@ -179,36 +150,33 @@ Geo.prototype = { if (data) { return View.prototype.dataToPoint.call(this, data, noRoam, out); } - }, + } - /** - * @override - */ - convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'), + convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: number[]): number[] { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + } - /** - * @override - */ - convertFromPixel: zrUtil.curry(doConvert, 'pointToData') + convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]): number[] { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + } }; zrUtil.mixin(Geo, View); -function doConvert(methodName, ecModel, finder, value) { - var geoModel = finder.geoModel; +function getCoordSys(finder: ParsedModelFinder): Geo { + var geoModel = finder.geoModel as GeoModel; var seriesModel = finder.seriesModel; - - var coordSys = geoModel + return geoModel ? geoModel.coordinateSystem : seriesModel ? ( - seriesModel.coordinateSystem // For map. - || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem + seriesModel.coordinateSystem as Geo // For map series. + || ((seriesModel.getReferringComponents('geo')[0] || {}) as GeoModel).coordinateSystem ) : null; - - return coordSys === this ? coordSys[methodName](value) : null; } -export default Geo; \ No newline at end of file +export default Geo; diff --git a/src/coord/geo/GeoModel.ts b/src/coord/geo/GeoModel.ts index 4f9361c..da28ae0 100644 --- a/src/coord/geo/GeoModel.ts +++ b/src/coord/geo/GeoModel.ts @@ -17,50 +17,106 @@ * under the License. */ -// @ts-nocheck import * as zrUtil from 'zrender/src/core/util'; import * as modelUtil from '../../util/model'; import ComponentModel from '../../model/Component'; import Model from '../../model/Model'; -import {DataSelectableMixin} from '../../component/helper/selectableMixin'; +import {DataSelectableMixin, DataSelectableOptionMixin, SelectableTarget} from '../../component/helper/selectableMixin'; import geoCreator from './geoCreator'; +import Geo from './Geo'; +import { ComponentOption, BoxLayoutOptionMixin, ItemStyleOption, ZRColor, LabelOption, DisplayState } from '../../util/types'; +import { RoamType } from '../../component/helper/RoamController'; +import { NameMap } from './geoTypes'; +import GlobalModel from '../../model/Global'; + + +export interface GeoItemStyleOption extends ItemStyleOption { + areaColor?: ZRColor; +}; +interface GeoLabelOption extends LabelOption { + formatter?: string | ((params: GeoLabelFormatterDataParams) => string); +} +interface GeoLabelFormatterDataParams { + name: string; + status: DisplayState; +} + +export interface RegoinOption extends SelectableTarget { + itemStyle?: GeoItemStyleOption; + label?: GeoLabelOption; + emphasis?: { + itemStyle?: GeoItemStyleOption; + label?: GeoLabelOption; + } +}; -var GeoModel = ComponentModel.extend({ +export interface GeoCommonOptionMixin { + // Map name + map: string; - type: 'geo', + // Aspect is width / height. Inited to be geoJson bbox aspect + // This parameter is used for scale this aspect + aspectScale?: number; - /** - * @type {module:echarts/coord/geo/Geo} - */ - coordinateSystem: null, + ///// Layout with center and size + // If you wan't to put map in a fixed size box with right aspect ratio + // This two properties may more conveninet + layoutCenter?: number[]; + layoutSize?: number; - layoutMode: 'box', + // Define left-top, right-bottom coords to control view + // For example, [ [180, 90], [-180, -90] ] + // higher priority than center and zoom + boundingCoords?: number[][]; + // Default on center of map + center?: number[]; + roam?: RoamType; + zoom?: number; - init: function (option) { - ComponentModel.prototype.init.apply(this, arguments); + scaleLimit?: { + min?: number; + max?: number; + }; - // Default label emphasis `show` - modelUtil.defaultEmphasis(option, 'label', ['show']); - }, + nameMap?: NameMap; +} - optionUpdated: function () { - var option = this.option; - var self = this; +export interface GeoOption extends + ComponentOption, + BoxLayoutOptionMixin, + DataSelectableOptionMixin, + GeoCommonOptionMixin { - option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap); + show?: boolean; + silent?: boolean; - this._optionModelMap = zrUtil.reduce(option.regions || [], function (optionModelMap, regionOpt) { - if (regionOpt.name) { - optionModelMap.set(regionOpt.name, new Model(regionOpt, self)); - } - return optionModelMap; - }, zrUtil.createHashMap()); + itemStyle?: GeoItemStyleOption; + label?: GeoLabelOption; - this.updateSelectedMap(option.regions); - }, + emphasis?: { + itemStyle?: GeoItemStyleOption; + label?: GeoLabelOption; + }; + + regions: RegoinOption[]; +} + +var LABEL_FORMATTER_NORMAL = ['label', 'formatter'] as const; +var LABEL_FORMATTER_EMPHASIS = ['emphasis', 'label', 'formatter'] as const; + +class GeoModel extends ComponentModel<GeoOption> { - defaultOption: { + static type = 'geo'; + readonly type = GeoModel.type; + + coordinateSystem: Geo; + + static layoutMode = 'box' as const; + + private _optionModelMap: zrUtil.HashMap<Model<RegoinOption>>; + + static defaultOption: GeoOption = { zlevel: 0, @@ -72,14 +128,6 @@ var GeoModel = ComponentModel.extend({ top: 'center', - - // width:, - // height:, - // right - // bottom - - // Aspect is width / height. Inited to be geoJson bbox aspect - // This parameter is used for scale this aspect // If svg used, aspectScale is 1 by default. // aspectScale: 0.75, aspectScale: null, @@ -131,33 +179,49 @@ var GeoModel = ComponentModel.extend({ }, regions: [] - }, + } + + init(option: GeoOption, parentModel: Model, ecModel: GlobalModel): void { + super.init(option, parentModel, ecModel); + // Default label emphasis `show` + modelUtil.defaultEmphasis(option, 'label', ['show']); + } + + optionUpdated(): void { + var option = this.option; + var self = this; + + option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap); + + this._optionModelMap = zrUtil.reduce(option.regions || [], function (optionModelMap, regionOpt) { + if (regionOpt.name) { + optionModelMap.set(regionOpt.name, new Model(regionOpt, self)); + } + return optionModelMap; + }, zrUtil.createHashMap()); + + this.updateSelectedMap(option.regions); + } /** - * Get model of region - * @param {string} name - * @return {module:echarts/model/Model} + * Get model of region. */ - getRegionModel: function (name) { + getRegionModel(name: string): Model<RegoinOption> { return this._optionModelMap.get(name) || new Model(null, this, this.ecModel); - }, + } /** * Format label - * @param {string} name Region name - * @param {string} [status='normal'] 'normal' or 'emphasis' - * @return {string} + * @param name Region name */ - getFormattedLabel: function (name, status) { + getFormattedLabel(name: string, status?: DisplayState) { var regionModel = this.getRegionModel(name); - var formatter = regionModel.get( - 'label' - + (status === 'normal' ? '.' : status + '.') - + 'formatter' - ); + var formatter = status === 'normal' + ? regionModel.get(LABEL_FORMATTER_NORMAL) + : regionModel.get(LABEL_FORMATTER_EMPHASIS); var params = { name: name - }; + } as GeoLabelFormatterDataParams; if (typeof formatter === 'function') { params.status = status; return formatter(params); @@ -165,17 +229,19 @@ var GeoModel = ComponentModel.extend({ else if (typeof formatter === 'string') { return formatter.replace('{a}', name != null ? name : ''); } - }, + } - setZoom: function (zoom) { + setZoom(zoom: number): void { this.option.zoom = zoom; - }, + } - setCenter: function (center) { + setCenter(center: number[]): void { this.option.center = center; } -}); -zrUtil.mixin(GeoModel, DataSelectableMixin.prototype); +} + +interface GeoModel extends DataSelectableMixin<GeoOption> {}; +zrUtil.mixin(GeoModel, DataSelectableMixin); -export default GeoModel; \ No newline at end of file +export default GeoModel; diff --git a/src/coord/geo/Region.ts b/src/coord/geo/Region.ts index 8b545d3..962924f 100644 --- a/src/coord/geo/Region.ts +++ b/src/coord/geo/Region.ts @@ -17,62 +17,54 @@ * under the License. */ -// @ts-nocheck - -/** - * @module echarts/coord/geo/Region - */ import BoundingRect from 'zrender/src/core/BoundingRect'; import * as bbox from 'zrender/src/core/bbox'; import * as vec2 from 'zrender/src/core/vector'; import * as polygonContain from 'zrender/src/contain/polygon'; +import { GeoJSON } from './geoTypes'; -/** - * @param {string|Region} name - * @param {Array} geometries - * @param {Array.<number>} cp - */ -function Region(name, geometries, cp) { - - /** - * @type {string} - * @readOnly - */ - this.name = name; - - /** - * @type {Array.<Array>} - * @readOnly - */ - this.geometries = geometries; - - if (!cp) { - var rect = this.getBoundingRect(); - cp = [ - rect.x + rect.width / 2, - rect.y + rect.height / 2 - ]; - } - else { - cp = [cp[0], cp[1]]; - } - /** - * @type {Array.<number>} - */ - this.center = cp; -} -Region.prototype = { +class Region { + + readonly geometries: { + type: 'polygon'; // FIXME:TS Is there other types? + exterior: number[][]; + interiors?: number[][][]; + }[]; + + readonly name: string; + + center: number[]; - constructor: Region, + // Injected outside. + properties: GeoJSON['features'][0]['properties']; - properties: null, + private _rect: BoundingRect; - /** - * @return {module:zrender/core/BoundingRect} - */ - getBoundingRect: function () { + + constructor( + name: string, + geometries: Region['geometries'], + cp: GeoJSON['features'][0]['properties']['cp'] + ) { + this.name = name; + this.geometries = geometries; + + if (!cp) { + var rect = this.getBoundingRect(); + cp = [ + rect.x + rect.width / 2, + rect.y + rect.height / 2 + ]; + } + else { + cp = [cp[0], cp[1]]; + } + this.center = cp; + } + + getBoundingRect(): BoundingRect { var rect = this._rect; if (rect) { return rect; @@ -81,8 +73,8 @@ Region.prototype = { var MAX_NUMBER = Number.MAX_VALUE; var min = [MAX_NUMBER, MAX_NUMBER]; var max = [-MAX_NUMBER, -MAX_NUMBER]; - var min2 = []; - var max2 = []; + var min2 = [] as number[]; + var max2 = [] as number[]; var geometries = this.geometries; for (var i = 0; i < geometries.length; i++) { // Only support polygon @@ -103,13 +95,9 @@ Region.prototype = { return (this._rect = new BoundingRect( min[0], min[1], max[0] - min[0], max[1] - min[1] )); - }, + } - /** - * @param {<Array.<number>} coord - * @return {boolean} - */ - contain: function (coord) { + contain(coord: number[]): boolean { var rect = this.getBoundingRect(); var geometries = this.geometries; if (!rect.contain(coord[0], coord[1])) { @@ -125,7 +113,7 @@ Region.prototype = { if (polygonContain.contain(exterior, coord[0], coord[1])) { // Not in the region if point is in the hole. for (var k = 0; k < (interiors ? interiors.length : 0); k++) { - if (polygonContain.contain(interiors[k])) { + if (polygonContain.contain(interiors[k], coord[0], coord[1])) { continue loopGeo; } } @@ -133,9 +121,9 @@ Region.prototype = { } } return false; - }, + } - transformTo: function (x, y, width, height) { + transformTo(x: number, y: number, width: number, height: number): void { var rect = this.getBoundingRect(); var aspect = rect.width / rect.height; if (!width) { @@ -170,15 +158,16 @@ Region.prototype = { rect.x + rect.width / 2, rect.y + rect.height / 2 ]; - }, + } - cloneShallow: function (name) { + cloneShallow(name: string): Region { name == null && (name = this.name); var newRegion = new Region(name, this.geometries, this.center); newRegion._rect = this._rect; newRegion.transformTo = null; // Simply avoid to be called. return newRegion; } -}; -export default Region; \ No newline at end of file +} + +export default Region; diff --git a/src/coord/geo/fix/diaoyuIsland.ts b/src/coord/geo/fix/diaoyuIsland.ts index 756a6fe..cc8b94b 100644 --- a/src/coord/geo/fix/diaoyuIsland.ts +++ b/src/coord/geo/fix/diaoyuIsland.ts @@ -1,3 +1,5 @@ +import Region from '../Region'; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -// @ts-nocheck - // Fix for 钓鱼岛 // var Region = require('../Region'); @@ -36,7 +36,7 @@ var points = [ ] ]; -export default function (mapType, region) { +export default function (mapType: string, region: Region) { if (mapType === 'china' && region.name === '台湾') { region.geometries.push({ type: 'polygon', diff --git a/src/coord/geo/fix/geoCoord.ts b/src/coord/geo/fix/geoCoord.ts index f2ff5f8..6da9959 100644 --- a/src/coord/geo/fix/geoCoord.ts +++ b/src/coord/geo/fix/geoCoord.ts @@ -1,3 +1,6 @@ +import Region from '../Region'; +import { Dictionary } from 'zrender/src/core/types'; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,15 +20,13 @@ * under the License. */ -// @ts-nocheck - var geoCoordMap = { 'Russia': [100, 60], 'United States': [-99, 38], 'United States of America': [-99, 38] -}; +} as Dictionary<number[]>; -export default function (mapType, region) { +export default function (mapType: string, region: Region) { if (mapType === 'world') { var geoCoord = geoCoordMap[region.name]; if (geoCoord) { diff --git a/src/coord/geo/fix/nanhai.ts b/src/coord/geo/fix/nanhai.ts index 4bdfc74..44d6f9f 100644 --- a/src/coord/geo/fix/nanhai.ts +++ b/src/coord/geo/fix/nanhai.ts @@ -17,8 +17,6 @@ * under the License. */ -// @ts-nocheck - // Fix for 南海诸岛 import * as zrUtil from 'zrender/src/core/util'; @@ -53,7 +51,7 @@ for (var i = 0; i < points.length; i++) { } } -export default function (mapType, regions) { +export default function (mapType: string, regions: Region[]) { if (mapType === 'china') { regions.push(new Region( '南海诸岛', diff --git a/src/coord/geo/fix/textCoord.ts b/src/coord/geo/fix/textCoord.ts index e1eaa9e..486fa0c 100644 --- a/src/coord/geo/fix/textCoord.ts +++ b/src/coord/geo/fix/textCoord.ts @@ -1,3 +1,6 @@ +import Region from '../Region'; +import { Dictionary } from 'zrender/src/core/types'; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,7 +20,6 @@ * under the License. */ -// @ts-nocheck var coordsOffsetMap = { '南海诸岛': [32, 80], @@ -27,9 +29,9 @@ var coordsOffsetMap = { '澳门': [-10, 10], //'北京': [-10, 0], '天津': [5, 5] -}; +} as Dictionary<number[]>; -export default function (mapType, region) { +export default function (mapType: string, region: Region) { if (mapType === 'china') { var coordFix = coordsOffsetMap[region.name]; if (coordFix) { diff --git a/src/coord/geo/geoCreator.ts b/src/coord/geo/geoCreator.ts index aac7428..db19dc5 100644 --- a/src/coord/geo/geoCreator.ts +++ b/src/coord/geo/geoCreator.ts @@ -17,7 +17,6 @@ * under the License. */ -// @ts-nocheck import {__DEV__} from '../../config'; import * as echarts from '../../echarts'; @@ -27,13 +26,23 @@ import * as layout from '../../util/layout'; import * as numberUtil from '../../util/number'; import geoSourceManager from './geoSourceManager'; import mapDataStorage from './mapDataStorage'; - +import GeoModel, { GeoOption, RegoinOption } from './GeoModel'; +import MapSeries, { MapSeriesOption } from '../../chart/map/MapSeries'; +import ExtensionAPI from '../../ExtensionAPI'; +import { CoordinateSystemCreator } from '../CoordinateSystem'; +import { NameMap } from './geoTypes'; +import SeriesModel from '../../model/Series'; +import { SeriesOption, SeriesOnGeoOptionMixin } from '../../util/types'; +import { Dictionary } from 'zrender/src/core/types'; +import GlobalModel from '../../model/Global'; +import ComponentModel from '../../model/Component'; + + +export type resizeGeoType = typeof resizeGeo; /** * Resize method bound to the geo - * @param {module:echarts/coord/geo/GeoModel|module:echarts/chart/map/MapModel} geoModel - * @param {module:echarts/ExtensionAPI} api */ -function resizeGeo(geoModel, api) { +function resizeGeo(this: Geo, geoModel: ComponentModel<GeoOption | MapSeriesOption>, api: ExtensionAPI): void { var boundingCoords = geoModel.get('boundingCoords'); if (boundingCoords != null) { @@ -51,8 +60,6 @@ function resizeGeo(geoModel, api) { var rect = this.getBoundingRect(); - var boxLayoutOption; - var center = geoModel.get('layoutCenter'); var size = geoModel.get('layoutSize'); @@ -80,9 +87,9 @@ function resizeGeo(geoModel, api) { } } - var viewRect; + var viewRect: layout.LayoutRect; if (useCenterAndSize) { - var viewRect = {}; + var viewRect = {} as layout.LayoutRect; if (aspect > 1) { // Width is same with size viewRect.width = size; @@ -97,7 +104,7 @@ function resizeGeo(geoModel, api) { } else { // Use left/top/width/height - boxLayoutOption = geoModel.getBoxLayoutParams(); + var boxLayoutOption = geoModel.getBoxLayoutParams() as Parameters<typeof layout.getLayoutRect>[0]; // 0.75 rate boxLayoutOption.aspect = aspect; @@ -114,27 +121,24 @@ function resizeGeo(geoModel, api) { this.setZoom(geoModel.get('zoom')); } -/** - * @param {module:echarts/coord/Geo} geo - * @param {module:echarts/model/Model} model - * @inner - */ -function setGeoCoords(geo, model) { +// Back compat for ECharts2, where the coord map is set on map series: +// {type: 'map', geoCoord: {'cityA': [116.46,39.92], 'cityA': [119.12,24.61]}}, +function setGeoCoords(geo: Geo, model: MapSeries) { zrUtil.each(model.get('geoCoord'), function (geoCoord, name) { geo.addGeoCoord(name, geoCoord); }); } -var geoCreator = { +class GeoCreator implements CoordinateSystemCreator { // For deciding which dimensions to use when creating list data - dimensions: Geo.prototype.dimensions, + dimensions = Geo.prototype.dimensions; - create: function (ecModel, api) { - var geoList = []; + create(ecModel: GlobalModel, api: ExtensionAPI): Geo[] { + var geoList = [] as Geo[]; // FIXME Create each time may be slow - ecModel.eachComponent('geo', function (geoModel, idx) { + ecModel.eachComponent('geo', function (geoModel: GeoModel, idx) { var name = geoModel.get('map'); var aspectScale = geoModel.get('aspectScale'); @@ -154,7 +158,7 @@ var geoCreator = { geo.zoomLimit = geoModel.get('scaleLimit'); geoList.push(geo); - setGeoCoords(geo, geoModel); + // setGeoCoords(geo, geoModel); geoModel.coordinateSystem = geo; geo.model = geoModel; @@ -168,15 +172,17 @@ var geoCreator = { ecModel.eachSeries(function (seriesModel) { var coordSys = seriesModel.get('coordinateSystem'); if (coordSys === 'geo') { - var geoIndex = seriesModel.get('geoIndex') || 0; + var geoIndex = ( + seriesModel as SeriesModel<SeriesOption & SeriesOnGeoOptionMixin> + ).get('geoIndex') || 0; seriesModel.coordinateSystem = geoList[geoIndex]; } }); // If has map series - var mapModelGroupBySeries = {}; + var mapModelGroupBySeries = {} as Dictionary<MapSeries[]>; - ecModel.eachSeriesByType('map', function (seriesModel) { + ecModel.eachSeriesByType('map', function (seriesModel: MapSeries) { if (!seriesModel.getHostGeoModel()) { var mapType = seriesModel.getMapType(); mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || []; @@ -209,16 +215,14 @@ var geoCreator = { }); return geoList; - }, + } /** * Fill given regions array - * @param {Array.<Object>} originRegionArr - * @param {string} mapName - * @param {Object} [nameMap] - * @return {Array} */ - getFilledRegions: function (originRegionArr, mapName, nameMap) { + getFilledRegions( + originRegionArr: RegoinOption[], mapName: string, nameMap?: NameMap + ): RegoinOption[] { // Not use the original var regionsArr = (originRegionArr || []).slice(); @@ -235,7 +239,9 @@ var geoCreator = { return regionsArr; } -}; +} + +const geoCreator = new GeoCreator(); echarts.registerCoordinateSystem('geo', geoCreator); diff --git a/src/coord/geo/geoJSONLoader.ts b/src/coord/geo/geoJSONLoader.ts index 3ec80f7..4e7df3e 100644 --- a/src/coord/geo/geoJSONLoader.ts +++ b/src/coord/geo/geoJSONLoader.ts @@ -17,8 +17,6 @@ * under the License. */ -// @ts-nocheck - import {each} from 'zrender/src/core/util'; import parseGeoJson from './parseGeoJson'; import {makeInner} from '../../util/model'; @@ -28,17 +26,22 @@ import fixNanhai from './fix/nanhai'; import fixTextCoord from './fix/textCoord'; import fixGeoCoord from './fix/geoCoord'; import fixDiaoyuIsland from './fix/diaoyuIsland'; +import { GeoJSONMapRecord } from './mapDataStorage'; +import { BoundingRect } from 'zrender/src/export'; +import Region from './Region'; + +type MapRecordInner = { + parsed: { + regions: Region[]; + boundingRect: BoundingRect; + }; +}; -var inner = makeInner(); +var inner = makeInner<MapRecordInner>(); export default { - /** - * @param {string} mapName - * @param {Object} mapRecord {specialAreas, geoJSON} - * @return {Object} {regions, boundingRect} - */ - load: function (mapName, mapRecord) { + load(mapName: string, mapRecord: GeoJSONMapRecord): MapRecordInner['parsed'] { var parsed = inner(mapRecord).parsed; @@ -84,7 +87,7 @@ export default { } }; -function getBoundingRect(regions) { +function getBoundingRect(regions: Region[]): BoundingRect { var rect; for (var i = 0; i < regions.length; i++) { var regionRect = regions[i].getBoundingRect(); diff --git a/src/coord/geo/geoSVGLoader.ts b/src/coord/geo/geoSVGLoader.ts index f735f8a..24b978c 100644 --- a/src/coord/geo/geoSVGLoader.ts +++ b/src/coord/geo/geoSVGLoader.ts @@ -17,25 +17,27 @@ * under the License. */ -// @ts-nocheck - import {parseSVG, makeViewBoxTransform} from 'zrender/src/tool/parseSVG'; import Group from 'zrender/src/container/Group'; import Rect from 'zrender/src/graphic/shape/Rect'; -import {assert, createHashMap} from 'zrender/src/core/util'; +import {assert, createHashMap, HashMap} from 'zrender/src/core/util'; import BoundingRect from 'zrender/src/core/BoundingRect'; import {makeInner} from '../../util/model'; +import { SVGMapRecord } from './mapDataStorage'; + +type MapRecordInner = { + originRoot: Group; + boundingRect: BoundingRect; + // key: hostKey, value: root + rootMap: HashMap<Group>; + originRootHostKey: string; +}; -var inner = makeInner(); +var inner = makeInner<MapRecordInner>(); export default { - /** - * @param {string} mapName - * @param {Object} mapRecord {specialAreas, geoJSON} - * @return {Object} {root, boundingRect} - */ - load: function (mapName, mapRecord) { + load(mapName: string, mapRecord: SVGMapRecord): ReturnType<typeof buildGraphic> { var originRoot = inner(mapRecord).originRoot; if (originRoot) { return { @@ -52,7 +54,7 @@ export default { return graphic; }, - makeGraphic: function (mapName, mapRecord, hostKey) { + makeGraphic(mapName: string, mapRecord: SVGMapRecord, hostKey: string): Group { // For performance consideration (in large SVG), graphic only maked // when necessary and reuse them according to hostKey. var field = inner(mapRecord); @@ -79,7 +81,7 @@ export default { return rootMap.set(hostKey, root); }, - removeGraphic: function (mapName, mapRecord, hostKey) { + removeGraphic(mapName: string, mapRecord: SVGMapRecord, hostKey: string): void { var field = inner(mapRecord); var rootMap = field.rootMap; rootMap && rootMap.removeKey(hostKey); @@ -89,7 +91,12 @@ export default { } }; -function buildGraphic(mapRecord, boundingRect) { +function buildGraphic( + mapRecord: SVGMapRecord, boundingRect?: BoundingRect +): { + root: Group; + boundingRect: BoundingRect; +} { var svgXML = mapRecord.svgXML; var result; var root; diff --git a/src/coord/geo/geoSourceManager.ts b/src/coord/geo/geoSourceManager.ts index 07554ac..2aa6696 100644 --- a/src/coord/geo/geoSourceManager.ts +++ b/src/coord/geo/geoSourceManager.ts @@ -17,32 +17,45 @@ * under the License. */ -// @ts-nocheck - import {__DEV__} from '../../config'; -import {each, createHashMap} from 'zrender/src/core/util'; -import mapDataStorage from './mapDataStorage'; +import {each, createHashMap, HashMap} from 'zrender/src/core/util'; +import mapDataStorage, { MapRecord } from './mapDataStorage'; import geoJSONLoader from './geoJSONLoader'; import geoSVGLoader from './geoSVGLoader'; import BoundingRect from 'zrender/src/core/BoundingRect'; +import { NameMap } from './geoTypes'; +import Region from './Region'; +import { Dictionary } from 'zrender/src/core/types'; +import Group from 'zrender/src/container/Group'; + +interface Loader { + load: (mapName: string, mapRecord: MapRecord) => { + regions?: Region[]; + boundingRect?: BoundingRect; + }; + makeGraphic?: (mapName: string, mapRecord: MapRecord, hostKey: string) => Group; + removeGraphic?: (mapName: string, mapRecord: MapRecord, hostKey: string) => void; +} var loaders = { geoJSON: geoJSONLoader, svg: geoSVGLoader -}; +} as Dictionary<Loader>; export default { - /** - * @param {string} mapName - * @param {Object} nameMap - * @return {Object} source {regions, regionsMap, nameCoordMap, boundingRect} - */ - load: function (mapName, nameMap) { - var regions = []; - var regionsMap = createHashMap(); - var nameCoordMap = createHashMap(); - var boundingRect; + load: function (mapName: string, nameMap: NameMap): { + regions: Region[]; + // Key: mapName + regionsMap: HashMap<Region>; + // Key: mapName + nameCoordMap: HashMap<number[]>; + boundingRect: BoundingRect + } { + var regions = [] as Region[]; + var regionsMap = createHashMap<Region>(); + var nameCoordMap = createHashMap<Region['center']>(); + var boundingRect: BoundingRect; var mapRecords = retrieveMap(mapName); each(mapRecords, function (record) { @@ -79,34 +92,32 @@ export default { }, /** - * @param {string} mapName - * @param {string} hostKey For cache. - * @return {Array.<module:zrender/Element>} Roots. + * @param hostKey For cache. + * @return Roots. */ - makeGraphic: makeInvoker('makeGraphic'), + makeGraphic: function (mapName: string, hostKey: string): Group[] { + var mapRecords = retrieveMap(mapName); + var results = [] as Group[]; + each(mapRecords, function (record) { + var method = loaders[record.type].makeGraphic; + method && results.push(method(mapName, record, hostKey)); + }); + return results; + }, /** - * @param {string} mapName - * @param {string} hostKey For cache. + * @param hostKey For cache. */ - removeGraphic: makeInvoker('removeGraphic') -}; - -function makeInvoker(methodName) { - return function (mapName, hostKey) { + removeGraphic: function (mapName: string, hostKey: string): void { var mapRecords = retrieveMap(mapName); - var results = []; - each(mapRecords, function (record) { - var method = loaders[record.type][methodName]; - method && results.push(method(mapName, record, hostKey)); + var method = loaders[record.type].makeGraphic; + method && method(mapName, record, hostKey); }); + } +}; - return results; - }; -} - -function mapNotExistsError(mapName) { +function mapNotExistsError(mapName: string): void { if (__DEV__) { console.error( 'Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.' @@ -114,7 +125,7 @@ function mapNotExistsError(mapName) { } } -function retrieveMap(mapName) { +function retrieveMap(mapName: string): MapRecord[] { var mapRecords = mapDataStorage.retrieveMap(mapName) || []; if (__DEV__) { diff --git a/src/coord/geo/geoTypes.ts b/src/coord/geo/geoTypes.ts new file mode 100644 index 0000000..6096510 --- /dev/null +++ b/src/coord/geo/geoTypes.ts @@ -0,0 +1,116 @@ +/* +* 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. +*/ + + +export interface NameMap { + [regionName: string]: string +} + +export interface GeoSpecialAreas { + [areaName: string]: { + left: number; + top: number; + width?: number; + height?: number; + } +} + +// Currently only `FeatureCollection` is supported in `parseGeoJson`? +export interface GeoJSON extends GeoJSONFeatureCollection<GeoJSONGeometry> { +} +export interface GeoJSONCompressed extends GeoJSONFeatureCollection<GeoJSONGeometryCompressed> { + UTF8Encoding?: boolean; + UTF8Scale?: number; +} +interface GeoJSONFeatureCollection<G> { + type: 'FeatureCollection'; + features: GeoJSONFeature<G>[]; +} +interface GeoJSONFeature<G = GeoJSONGeometry> { + type: 'Feature'; + id?: string | number; + properties: { + name?: string; + cp?: number[]; + // id: string; + // childNum: number; + // Actual in GeoJSON spec, properties can be any. + [key: string]: any; + }; + geometry: G; +} +type GeoJSONGeometry = + GeoJSONGeometryPoint + | GeoJSONGeometryMultiPoint + | GeoJSONGeometryLineString + | GeoJSONGeometryMultiLineString + | GeoJSONGeometryPolygon + | GeoJSONGeometryMultiPolygon + // Do not support `GeometryCollection` yet. + // | GeoJSONGeometryGeometryCollection + +type GeoJSONGeometryCompressed = + GeoJSONGeometryPoint + | GeoJSONGeometryMultiPoint + | GeoJSONGeometryLineString + | GeoJSONGeometryMultiLineString + // Currenly only Polygon and MultiPolygon can be parsed from compression. + | GeoJSONGeometryPolygonCompressed + | GeoJSONGeometryMultiPolygonCompressed + // Do not support `GeometryCollection` yet. + // | GeoJSONGeometryGeometryCollection + +interface GeoJSONGeometryPoint { + type: 'Point'; + coordinates: number[]; +}; +interface GeoJSONGeometryMultiPoint { + type: 'MultiPoint'; + coordinates: number[][]; +}; +interface GeoJSONGeometryLineString { + type: 'LineString'; + coordinates: number[][]; +}; +interface GeoJSONGeometryMultiLineString { + type: 'MultiLineString'; + coordinates: number[][][]; +}; +export interface GeoJSONGeometryPolygon { + type: 'Polygon'; + coordinates: number[][][]; +}; +interface GeoJSONGeometryPolygonCompressed { + type: 'Polygon'; + coordinates: string[]; + encodeOffsets: number[][] +}; +export interface GeoJSONGeometryMultiPolygon { + type: 'MultiPolygon'; + coordinates: number[][][][]; +}; +interface GeoJSONGeometryMultiPolygonCompressed { + type: 'MultiPolygon'; + coordinates: string[][]; + encodeOffsets: number[][][]; +}; +// interface GeoJSONGeometryGeometryCollection { +// type: 'GeometryCollection'; +// geometries: GeoJSONGeometry[]; +// }; diff --git a/src/coord/geo/mapDataStorage.ts b/src/coord/geo/mapDataStorage.ts index 54be749..2453878 100644 --- a/src/coord/geo/mapDataStorage.ts +++ b/src/coord/geo/mapDataStorage.ts @@ -17,40 +17,40 @@ * under the License. */ -// @ts-nocheck - import {__DEV__} from '../../config'; import {createHashMap, isString, isArray, each, assert} from 'zrender/src/core/util'; import {parseXML} from 'zrender/src/tool/parseSVG'; +import { GeoSpecialAreas, GeoJSON, GeoJSONCompressed } from './geoTypes'; +import { Dictionary } from 'zrender/src/core/types'; // For minimize the code size of common echarts package, // do not put too much logic in this module. -export type GeoMapSVGSource = 'string' | Document; -export type GeoMapGeoJSONSource = 'string' | object; -export type GeoSpecialAreas = object; - -interface GeoMapGeoJSONDefinition { - geoJSON?: GeoMapGeoJSONSource; - geoJson?: GeoMapGeoJSONSource; - specialAreas?: GeoSpecialAreas; -} -interface GeoMapSVGDefinition { - svg?: GeoMapSVGSource; +type SVGMapSource = 'string' | Document | SVGElement; +type GeoJSONMapSource = 'string' | GeoJSON | GeoJSONCompressed; +type MapInputObject = { + geoJSON?: GeoJSONMapSource; + geoJson?: GeoJSONMapSource; + svg?: SVGMapSource; specialAreas?: GeoSpecialAreas; } -export type GeoMapDefinition = GeoMapGeoJSONDefinition | GeoMapSVGDefinition; -interface GeoMapRecord { - type: 'geoJSON' | 'svg'; - source: GeoMapGeoJSONSource | GeoMapSVGSource; +export type MapRecord = GeoJSONMapRecord | SVGMapRecord; +export interface GeoJSONMapRecord { + type: 'geoJSON'; + source: GeoJSONMapSource; + specialAreas: GeoSpecialAreas; + geoJSON: GeoJSON | GeoJSONCompressed; +} +export interface SVGMapRecord { + type: 'svg'; + source: SVGMapSource; specialAreas: GeoSpecialAreas; - geoJSON: object; - svgXML: Node + svgXML: ReturnType<typeof parseXML>; } -var storage = createHashMap<GeoMapRecord[]>(); +var storage = createHashMap<MapRecord[]>(); export default { @@ -82,40 +82,40 @@ export default { */ registerMap: function ( mapName: string, - rawGeoJson: GeoMapDefinition | GeoMapDefinition[] | GeoMapGeoJSONSource, + rawDef: MapInputObject | MapRecord[] | GeoJSONMapSource, rawSpecialAreas?: GeoSpecialAreas - ): GeoMapRecord[] { + ): MapRecord[] { - var records; + var records: MapRecord[]; - if (isArray(rawGeoJson)) { - records = rawGeoJson; + if (isArray(rawDef)) { + records = rawDef as MapRecord[]; } - else if ((rawGeoJson as GeoMapSVGDefinition).svg) { + else if ((rawDef as MapInputObject).svg) { records = [{ type: 'svg', - source: (rawGeoJson as GeoMapSVGDefinition).svg, - specialAreas: (rawGeoJson as GeoMapSVGDefinition).specialAreas - }]; + source: (rawDef as MapInputObject).svg, + specialAreas: (rawDef as MapInputObject).specialAreas + } as SVGMapRecord]; } else { // Backward compatibility. - var geoSource = (rawGeoJson as GeoMapGeoJSONDefinition).geoJson - || (rawGeoJson as GeoMapGeoJSONDefinition).geoJSON; - if (geoSource && !(rawGeoJson as any).features) { - rawSpecialAreas = (rawGeoJson as GeoMapGeoJSONDefinition).specialAreas; - rawGeoJson = geoSource; + var geoSource = (rawDef as MapInputObject).geoJson + || (rawDef as MapInputObject).geoJSON; + if (geoSource && !(rawDef as GeoJSON).features) { + rawSpecialAreas = (rawDef as MapInputObject).specialAreas; + rawDef = geoSource; } records = [{ type: 'geoJSON', - source: rawGeoJson, + source: rawDef as GeoJSONMapSource, specialAreas: rawSpecialAreas - }]; + } as GeoJSONMapRecord]; } each(records, function (record) { var type = record.type; - type === 'geoJson' && (type = record.type = 'geoJSON'); + (type as any) === 'geoJson' && (type = record.type = 'geoJSON'); var parse = parsers[type]; @@ -129,15 +129,15 @@ export default { return storage.set(mapName, records); }, - retrieveMap: function (mapName: string): GeoMapRecord[] { + retrieveMap: function (mapName: string): MapRecord[] { return storage.get(mapName); } }; -var parsers = { +var parsers: Dictionary<(record: MapRecord) => void> = { - geoJSON: function (record: GeoMapRecord): void { + geoJSON: function (record: GeoJSONMapRecord): void { var source = record.source; record.geoJSON = !isString(source) ? source @@ -152,8 +152,8 @@ var parsers = { // if we do it here, the clone of zrender elements has to be // required. So we do it once for each geo instance, util real // performance issues call for optimizing it. - svg: function (record: GeoMapRecord): void { - record.svgXML = parseXML(record.source as GeoMapSVGSource); + svg: function (record: SVGMapRecord): void { + record.svgXML = parseXML(record.source as SVGMapSource); } }; diff --git a/src/coord/geo/parseGeoJson.ts b/src/coord/geo/parseGeoJson.ts index 7bb5aef..463126c 100644 --- a/src/coord/geo/parseGeoJson.ts +++ b/src/coord/geo/parseGeoJson.ts @@ -17,61 +17,66 @@ * under the License. */ -// @ts-nocheck - /** * Parse and decode geo json - * @module echarts/coord/geo/parseGeoJson */ import * as zrUtil from 'zrender/src/core/util'; import Region from './Region'; +import { GeoJSONCompressed, GeoJSON } from './geoTypes'; + -function decode(json) { - if (!json.UTF8Encoding) { - return json; +function decode(json: GeoJSONCompressed | GeoJSON): GeoJSON { + if (!(json as GeoJSONCompressed).UTF8Encoding) { + return json as GeoJSON; } - var encodeScale = json.UTF8Scale; + var jsonCompressed = json as GeoJSONCompressed; + var encodeScale = jsonCompressed.UTF8Scale; if (encodeScale == null) { encodeScale = 1024; } - var features = json.features; + var features = jsonCompressed.features; for (var f = 0; f < features.length; f++) { var feature = features[f]; var geometry = feature.geometry; - var coordinates = geometry.coordinates; - var encodeOffsets = geometry.encodeOffsets; - - for (var c = 0; c < coordinates.length; c++) { - var coordinate = coordinates[c]; - if (geometry.type === 'Polygon') { + if (geometry.type === 'Polygon') { + let coordinates = geometry.coordinates; + for (let c = 0; c < coordinates.length; c++) { coordinates[c] = decodePolygon( - coordinate, - encodeOffsets[c], + coordinates[c], + geometry.encodeOffsets[c], encodeScale - ); + ) as any; } - else if (geometry.type === 'MultiPolygon') { + } + else if (geometry.type === 'MultiPolygon') { + let coordinates = geometry.coordinates; + for (let c = 0; c < coordinates.length; c++) { + let coordinate = coordinates[c]; for (var c2 = 0; c2 < coordinate.length; c2++) { - var polygon = coordinate[c2]; coordinate[c2] = decodePolygon( - polygon, - encodeOffsets[c][c2], + coordinate[c2], + geometry.encodeOffsets[c][c2], encodeScale - ); + ) as any; } } } } // Has been decoded - json.UTF8Encoding = false; - return json; + jsonCompressed.UTF8Encoding = false; + + return jsonCompressed as GeoJSON; } -function decodePolygon(coordinate, encodeOffsets, encodeScale) { +function decodePolygon( + coordinate: string, + encodeOffsets: number[], + encodeScale: number +): number[][] { var result = []; var prevX = encodeOffsets[0]; var prevY = encodeOffsets[1]; @@ -95,14 +100,9 @@ function decodePolygon(coordinate, encodeOffsets, encodeScale) { return result; } -/** - * @alias module:echarts/coord/geo/parseGeoJson - * @param {Object} geoJson - * @return {module:zrender/container/Group} - */ -export default function (geoJson) { +export default function (geoJson: GeoJSON | GeoJSONCompressed): Region[] { - decode(geoJson); + geoJson = decode(geoJson); return zrUtil.map(zrUtil.filter(geoJson.features, function (featureObj) { // Output of mapshaper may have geometry null @@ -110,13 +110,12 @@ export default function (geoJson) { && featureObj.properties && featureObj.geometry.coordinates.length > 0; }), function (featureObj) { - var properties = featureObj.properties; - var geo = featureObj.geometry; + let properties = featureObj.properties; + let geo = featureObj.geometry; - var coordinates = geo.coordinates; - - var geometries = []; + let geometries = [] as Region['geometries']; if (geo.type === 'Polygon') { + let coordinates = geo.coordinates; geometries.push({ type: 'polygon', // According to the GeoJSON specification. @@ -126,6 +125,7 @@ export default function (geoJson) { }); } if (geo.type === 'MultiPolygon') { + let coordinates = geo.coordinates; zrUtil.each(coordinates, function (item) { if (item[0]) { geometries.push({ @@ -137,12 +137,12 @@ export default function (geoJson) { }); } - var region = new Region( + let region = new Region( properties.name, geometries, - properties.cp + properties.cp, ); region.properties = properties; return region; }); -} \ No newline at end of file +} diff --git a/src/coord/geo/prepareCustom.ts b/src/coord/geo/prepareCustom.ts index 8d329a8..df0fc16 100644 --- a/src/coord/geo/prepareCustom.ts +++ b/src/coord/geo/prepareCustom.ts @@ -17,11 +17,10 @@ * under the License. */ -// @ts-nocheck - import * as zrUtil from 'zrender/src/core/util'; +import Geo from './Geo'; -function dataToCoordSize(dataSize, dataItem) { +function dataToCoordSize(this: Geo, dataSize: number[], dataItem: number[]): number[] { dataItem = dataItem || [0, 0]; return zrUtil.map([0, 1], function (dimIdx) { var val = dataItem[dimIdx]; @@ -35,7 +34,7 @@ function dataToCoordSize(dataSize, dataItem) { }, this); } -export default function (coordSys) { +export default function (coordSys: Geo) { var rect = coordSys.getBoundingRect(); return { coordSys: { @@ -47,7 +46,7 @@ export default function (coordSys) { zoom: coordSys.getZoom() }, api: { - coord: function (data) { + coord: function (data: number[]): number[] { // do not provide "out" and noRoam param, // Compatible with this usage: // echarts.util.map(item.points, api.coord) diff --git a/src/echarts.ts b/src/echarts.ts index c369088..596573b 100644 --- a/src/echarts.ts +++ b/src/echarts.ts @@ -47,7 +47,7 @@ import Scheduler from './stream/Scheduler'; import lightTheme from './theme/light'; import darkTheme from './theme/dark'; import './component/dataset'; -import mapDataStorage, { GeoMapDefinition, GeoMapGeoJSONSource, GeoSpecialAreas } from './coord/geo/mapDataStorage'; +import mapDataStorage from './coord/geo/mapDataStorage'; import {CoordinateSystemMaster, CoordinateSystemCreator, CoordinateSystemHostModel} from './coord/CoordinateSystem'; import { parseClassType } from './util/clazz'; import {ECEventProcessor} from './util/ECEventProcessor'; @@ -2254,9 +2254,9 @@ export function setCanvasCreator(creator: () => HTMLCanvasElement): void { * Compatible with previous `echarts.registerMap`. */ export function registerMap( - mapName: string, - geoJson: GeoMapDefinition | GeoMapDefinition[] | GeoMapGeoJSONSource, - specialAreas?: GeoSpecialAreas + mapName: Parameters<typeof mapDataStorage.registerMap>[0], + geoJson: Parameters<typeof mapDataStorage.registerMap>[1], + specialAreas?: Parameters<typeof mapDataStorage.registerMap>[2] ): void { mapDataStorage.registerMap(mapName, geoJson, specialAreas); } @@ -2264,8 +2264,9 @@ export function registerMap( export function getMap(mapName: string) { // For backward compatibility, only return the first one. var records = mapDataStorage.retrieveMap(mapName); - // FIXME support SVG + // FIXME support SVG, where return not only records[0]. return records && records[0] && { + // @ts-ignore geoJson: records[0].geoJSON, specialAreas: records[0].specialAreas }; diff --git a/src/model/Component.ts b/src/model/Component.ts index 9c1ca02..c918474 100644 --- a/src/model/Component.ts +++ b/src/model/Component.ts @@ -271,7 +271,6 @@ class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Mode }); } - getBoxLayoutParams() { // Consider itself having box layout configs. const boxLayoutModel = this as Model<ComponentOption & BoxLayoutOptionMixin>; diff --git a/src/model/Series.ts b/src/model/Series.ts index 4f91679..80c5a5f 100644 --- a/src/model/Series.ts +++ b/src/model/Series.ts @@ -327,10 +327,14 @@ class SeriesModel<Opt extends SeriesOption = SeriesOption> extends ComponentMode multipleSeries?: boolean, dataType?: string, renderMode?: TooltipRenderMode - ): { - html: string, - markers: {[markName: string]: string} - } { + ): + { + html: string, + markers: {[markName: string]: string} + } + // The override method can only return string + | string + { var series = this; renderMode = renderMode || 'html'; diff --git a/src/util/graphic.ts b/src/util/graphic.ts index 9fa2b48..6f7ee97 100644 --- a/src/util/graphic.ts +++ b/src/util/graphic.ts @@ -678,7 +678,7 @@ export function setHoverStyle(el: Element, hoverStyle?: StyleProps) { */ export function setAsHighDownDispatcher(el: Element, asDispatcher: boolean) { const disable = asDispatcher === false; - const extendedEl = el as ExtendedDisplayable; + const extendedEl = el as ExtendedElement; // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly. extendedEl.__highDownSilentOnTouch = (el as ECElement).highDownSilentOnTouch; @@ -720,29 +720,32 @@ export function getHighlightDigit(highlightKey: number) { return highlightDigit; } +interface SetLabelStyleOpt<LDI> extends TextCommonParams { + defaultText?: string | ( + (labelDataIndex: LDI, opt: SetLabelStyleOpt<LDI>) => string + ), + // Fetch text by `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)` + labelFetcher?: { + getFormattedLabel?: ( + // In MapDraw case it can be string (region name) + labelDataIndex: LDI, + state: DisplayState, + dataType: string, + labelDimIndex: number + ) => string + }, + labelDataIndex?: LDI, + labelDimIndex?: number +} /** * See more info in `setTextStyleCommon`. */ -export function setLabelStyle( +export function setLabelStyle<LDI>( normalStyle: StyleProps, emphasisStyle: StyleProps, normalModel: Model, emphasisModel: Model, - opt?: { - defaultText?: string, - // Fetch text by `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex)` - labelFetcher?: { - getFormattedLabel?: ( - labelDataIndex: number, - state: - DisplayState, - dataType: string, - labelDimIndex: number - ) => string - }, - labelDataIndex?: number, - labelDimIndex?: number - } & TextCommonParams, + opt?: SetLabelStyleOpt<LDI>, normalSpecified?: StyleProps, emphasisSpecified?: StyleProps ) { diff --git a/src/util/types.ts b/src/util/types.ts index 468fe91..df725ed 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -405,7 +405,12 @@ export type OptionDataItem = | Dictionary<OptionDataValue> | ArrayLike<OptionDataValue> // FIXME: In some case (markpoint in geo (geo-map.html)), dataItem is {coord: [...]} - | {value: ArrayLike<OptionDataValue>}; // Only for `SOURCE_FORMAT_KEYED_ORIGINAL` + | OptionDataItemObject<OptionDataValue>; +// Only for `SOURCE_FORMAT_KEYED_ORIGINAL` +export type OptionDataItemObject<T> = { + name?: string + value?: T[] | T +}; export type OptionDataValue = string | number | Date; export type OptionDataValueNumeric = number | '-'; @@ -1026,4 +1031,15 @@ export interface SeriesOnPolarOptionMixin { export interface SeriesOnSingleOptionMixin { singleAxisIndex?: number singleAxisId?: string -} \ No newline at end of file +} + +export interface SeriesOnGeoOptionMixin { + geoIndex?: number; +} + +export interface SeriesEncodeOptionMixin { + datasetIndex?: number; + seriesLayoutBy?: SeriesLayoutBy; + dimentions?: DimensionName[]; + encode?: OptionEncode +} diff --git a/src/view/Chart.ts b/src/view/Chart.ts index d206483..19a1ec6 100644 --- a/src/view/Chart.ts +++ b/src/view/Chart.ts @@ -37,12 +37,12 @@ import { SeriesTaskContext, SeriesTask } from '../stream/Scheduler'; import List from '../data/List'; var inner = modelUtil.makeInner<{ - updateMethod: keyof Chart + updateMethod: keyof ChartView }>(); var renderPlanner = createRenderPlanner(); -class Chart { +class ChartView { // [Caution]: for compat the previous "class extend" // publich and protected fields must be initialized on @@ -67,7 +67,7 @@ class Chart { __id: string; static protoInitialize = (function () { - var proto = Chart.prototype; + var proto = ChartView.prototype; proto.type = 'chart'; })(); @@ -178,7 +178,7 @@ class Chart { this.render(seriesModel, ecModel, api, payload); } - static markUpdateMethod(payload: Payload, methodName: keyof Chart): void { + static markUpdateMethod(payload: Payload, methodName: keyof ChartView): void { inner(payload).updateMethod = methodName; } @@ -222,12 +222,12 @@ function toggleHighlight(data: List, payload: Payload, state: DisplayState) { } } -export type ChartViewConstructor = typeof Chart +export type ChartViewConstructor = typeof ChartView & clazzUtil.ExtendableConstructor & clazzUtil.ClassManager; -clazzUtil.enableClassExtend(Chart as ChartViewConstructor, ['dispose']); -clazzUtil.enableClassManagement(Chart as ChartViewConstructor, {registerWhenExtend: true}); +clazzUtil.enableClassExtend(ChartView as ChartViewConstructor, ['dispose']); +clazzUtil.enableClassManagement(ChartView as ChartViewConstructor, {registerWhenExtend: true}); function renderTaskPlan(context: SeriesTaskContext): StageHandlerPlanReturn { @@ -244,7 +244,7 @@ function renderTaskReset(context: SeriesTaskContext): TaskResetCallbackReturn<Se var view = context.view; var updateMethod = payload && inner(payload).updateMethod; - var methodName: keyof Chart = progressiveRender + var methodName: keyof ChartView = progressiveRender ? 'incrementalPrepareRender' : (updateMethod && view[updateMethod]) ? updateMethod @@ -281,4 +281,4 @@ var progressMethodMap: {[method: string]: TaskResetCallbackReturn<SeriesTaskCont } }; -export default Chart; +export default ChartView; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
