Spaces:
Running
Running
| /* | |
| * 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. | |
| */ | |
| import * as zrUtil from 'zrender/src/core/util'; | |
| import createSeriesDataSimply from '../helper/createSeriesDataSimply'; | |
| import SeriesModel from '../../model/Series'; | |
| import geoSourceManager from '../../coord/geo/geoSourceManager'; | |
| import {makeSeriesEncodeForNameBased} from '../../data/helper/sourceHelper'; | |
| import { | |
| SeriesOption, | |
| BoxLayoutOptionMixin, | |
| SeriesEncodeOptionMixin, | |
| OptionDataItemObject, | |
| OptionDataValueNumeric, | |
| ParsedValue, | |
| SeriesOnGeoOptionMixin, | |
| StatesOptionMixin, | |
| SeriesLabelOption, | |
| StatesMixinBase, | |
| CallbackDataParams | |
| } from '../../util/types'; | |
| import { Dictionary } from 'zrender/src/core/types'; | |
| import GeoModel, { GeoCommonOptionMixin, GeoItemStyleOption } from '../../coord/geo/GeoModel'; | |
| import SeriesData from '../../data/SeriesData'; | |
| import Model from '../../model/Model'; | |
| import Geo from '../../coord/geo/Geo'; | |
| import { createTooltipMarkup } from '../../component/tooltip/tooltipMarkup'; | |
| import {createSymbol, ECSymbol} from '../../util/symbol'; | |
| import {LegendIconParams} from '../../component/legend/LegendModel'; | |
| import {Group} from '../../util/graphic'; | |
| export interface MapStateOption<TCbParams = never> { | |
| itemStyle?: GeoItemStyleOption<TCbParams> | |
| label?: SeriesLabelOption | |
| } | |
| export interface MapDataItemOption extends MapStateOption, | |
| StatesOptionMixin<MapStateOption, StatesMixinBase>, | |
| OptionDataItemObject<OptionDataValueNumeric> { | |
| cursor?: string | |
| } | |
| export type MapValueCalculationType = 'sum' | 'average' | 'min' | 'max'; | |
| export interface MapSeriesOption extends | |
| SeriesOption<MapStateOption<CallbackDataParams>, StatesMixinBase>, | |
| MapStateOption<CallbackDataParams>, | |
| 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, | |
| SeriesEncodeOptionMixin { | |
| type?: 'map' | |
| coordinateSystem?: string; | |
| silent?: boolean; | |
| // 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)[] | |
| nameProperty?: string; | |
| } | |
| class MapSeries extends SeriesModel<MapSeriesOption> { | |
| static type = 'series.map' as const; | |
| type = MapSeries.type; | |
| static dependencies = ['geo']; | |
| static layoutMode = 'box' as const; | |
| coordinateSystem: Geo; | |
| // ----------------- | |
| // Injected outside | |
| originalData: SeriesData; | |
| 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(this: MapSeries, option: MapSeriesOption): SeriesData { | |
| const data = createSeriesDataSimply(this, { | |
| coordDimensions: ['value'], | |
| encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this) | |
| }); | |
| const dataNameMap = zrUtil.createHashMap(); | |
| const toAppendNames = [] as string[]; | |
| for (let i = 0, len = data.count(); i < len; i++) { | |
| const name = data.getName(i); | |
| dataNameMap.set(name, true); | |
| } | |
| const geoSource = geoSourceManager.load(this.getMapType(), this.option.nameMap, this.option.nameProperty); | |
| zrUtil.each(geoSource.regions, function (region) { | |
| const name = region.name; | |
| if (!dataNameMap.get(name)) { | |
| toAppendNames.push(name); | |
| } | |
| }); | |
| // Complete data with missing regions. The consequent processes (like visual | |
| // map and render) can not be performed without a "full data". For example, | |
| // find `dataIndex` by name. | |
| data.appendValues([], toAppendNames); | |
| return data; | |
| } | |
| /** | |
| * If no host geo model, return null, which means using a | |
| * inner exclusive geo model. | |
| */ | |
| getHostGeoModel(): GeoModel { | |
| const geoIndex = this.option.geoIndex; | |
| return geoIndex != null | |
| ? this.ecModel.getComponent('geo', geoIndex) as GeoModel | |
| : null; | |
| } | |
| getMapType(): string { | |
| return (this.getHostGeoModel() || this).option.map; | |
| } | |
| // _fillOption(option, mapName) { | |
| // Shallow clone | |
| // option = zrUtil.extend({}, option); | |
| // option.data = geoCreator.getFilledRegions(option.data, mapName, option.nameMap); | |
| // return option; | |
| // } | |
| getRawValue(dataIndex: number): ParsedValue { | |
| // Use value stored in data instead because it is calculated from multiple series | |
| // FIXME Provide all value of multiple series ? | |
| const data = this.getData(); | |
| return data.get(data.mapDimension('value'), dataIndex); | |
| } | |
| /** | |
| * Get model of region | |
| */ | |
| getRegionModel(regionName: string): Model<MapDataItemOption> { | |
| const data = this.getData(); | |
| return data.getItemModel(data.indexOfName(regionName)); | |
| } | |
| /** | |
| * Map tooltip formatter | |
| */ | |
| formatTooltip( | |
| dataIndex: number, | |
| multipleSeries: boolean, | |
| dataType: string | |
| ) { | |
| // FIXME orignalData and data is a bit confusing | |
| const data = this.getData(); | |
| const value = this.getRawValue(dataIndex); | |
| const name = data.getName(dataIndex); | |
| const seriesGroup = this.seriesGroup; | |
| const seriesNames = []; | |
| for (let i = 0; i < seriesGroup.length; i++) { | |
| const otherIndex = seriesGroup[i].originalData.indexOfName(name); | |
| const valueDim = data.mapDimension('value'); | |
| if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex) as number)) { | |
| seriesNames.push(seriesGroup[i].name); | |
| } | |
| } | |
| return createTooltipMarkup('section', { | |
| header: seriesNames.join(', '), | |
| noHeader: !seriesNames.length, | |
| blocks: [createTooltipMarkup('nameValue', { | |
| name: name, value: value | |
| })] | |
| }); | |
| } | |
| getTooltipPosition = function (this: MapSeries, dataIndex: number): number[] { | |
| if (dataIndex != null) { | |
| const name = this.getData().getName(dataIndex); | |
| const geo = this.coordinateSystem; | |
| const region = geo.getRegion(name); | |
| return region && geo.dataToPoint(region.getCenter()); | |
| } | |
| }; | |
| setZoom(zoom: number): void { | |
| this.option.zoom = zoom; | |
| } | |
| setCenter(center: number[]): void { | |
| this.option.center = center; | |
| } | |
| getLegendIcon(opt: LegendIconParams): ECSymbol | Group { | |
| const iconType = opt.icon || 'roundRect'; | |
| const icon = createSymbol( | |
| iconType, | |
| 0, | |
| 0, | |
| opt.itemWidth, | |
| opt.itemHeight, | |
| opt.itemStyle.fill | |
| ); | |
| icon.setStyle(opt.itemStyle); | |
| // Map do not use itemStyle.borderWidth as border width | |
| icon.style.stroke = 'none'; | |
| // No rotation because no series visual symbol for map | |
| if (iconType.indexOf('empty') > -1) { | |
| icon.style.stroke = icon.style.fill; | |
| icon.style.fill = '#fff'; | |
| icon.style.lineWidth = 2; | |
| } | |
| return icon; | |
| } | |
| static defaultOption: MapSeriesOption = { | |
| // 一级层叠 | |
| // zlevel: 0, | |
| // 二级层叠 | |
| z: 2, | |
| coordinateSystem: 'geo', | |
| // map should be explicitly specified since ec3. | |
| map: '', | |
| // If `geoIndex` is not specified, a exclusive geo will be | |
| // created. Otherwise use the specified geo component, and | |
| // `map` and `mapType` are ignored. | |
| // geoIndex: 0, | |
| // 'center' | 'left' | 'right' | 'x%' | {number} | |
| left: 'center', | |
| // 'center' | 'top' | 'bottom' | 'x%' | {number} | |
| top: 'center', | |
| // right | |
| // bottom | |
| // width: | |
| // height | |
| // Aspect is width / height. Inited to be geoJson bbox aspect | |
| // This parameter is used for scale this aspect | |
| // Default value: | |
| // for geoSVG source: 1, | |
| // for geoJSON source: 0.75. | |
| aspectScale: null, | |
| // Layout with center and size | |
| // If you want to put map in a fixed size box with right aspect ratio | |
| // This two properties may be more convenient. | |
| // layoutCenter: [50%, 50%] | |
| // layoutSize: 100 | |
| showLegendSymbol: true, | |
| // Define left-top, right-bottom coords to control view | |
| // For example, [ [180, 90], [-180, -90] ], | |
| // higher priority than center and zoom | |
| boundingCoords: null, | |
| // Default on center of map | |
| center: null, | |
| zoom: 1, | |
| scaleLimit: null, | |
| selectedMode: true, | |
| label: { | |
| show: false, | |
| color: '#000' | |
| }, | |
| // scaleLimit: null, | |
| itemStyle: { | |
| borderWidth: 0.5, | |
| borderColor: '#444', | |
| areaColor: '#eee' | |
| }, | |
| emphasis: { | |
| label: { | |
| show: true, | |
| color: 'rgb(100,0,0)' | |
| }, | |
| itemStyle: { | |
| areaColor: 'rgba(255,215,0,0.8)' | |
| } | |
| }, | |
| select: { | |
| label: { | |
| show: true, | |
| color: 'rgb(100,0,0)' | |
| }, | |
| itemStyle: { | |
| color: 'rgba(255,215,0,0.8)' | |
| } | |
| }, | |
| nameProperty: 'name' | |
| }; | |
| } | |
| export default MapSeries; | |