| /* | |
| * 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 * as modelUtil from '../../util/model'; | |
| import ComponentModel from '../../model/Component'; | |
| import Model from '../../model/Model'; | |
| import geoCreator from './geoCreator'; | |
| import Geo from './Geo'; | |
| import { | |
| ComponentOption, | |
| BoxLayoutOptionMixin, | |
| ItemStyleOption, | |
| ZRColor, | |
| LabelOption, | |
| DisplayState, | |
| RoamOptionMixin, | |
| AnimationOptionMixin, | |
| StatesOptionMixin, | |
| Dictionary, | |
| CommonTooltipOption, | |
| StatesMixinBase | |
| } from '../../util/types'; | |
| import { GeoProjection, NameMap } from './geoTypes'; | |
| import GlobalModel from '../../model/Global'; | |
| import geoSourceManager from './geoSourceManager'; | |
| export interface GeoItemStyleOption<TCbParams = never> extends ItemStyleOption<TCbParams> { | |
| areaColor?: ZRColor; | |
| }; | |
| interface GeoLabelOption extends LabelOption { | |
| formatter?: string | ((params: GeoLabelFormatterDataParams) => string); | |
| } | |
| export interface GeoStateOption { | |
| itemStyle?: GeoItemStyleOption | |
| // FIXME:TS formatter? | |
| label?: GeoLabelOption | |
| } | |
| interface GeoLabelFormatterDataParams { | |
| name: string; | |
| status: DisplayState; | |
| } | |
| export interface RegoinOption extends GeoStateOption, StatesOptionMixin<GeoStateOption, StatesMixinBase> { | |
| name?: string | |
| selected?: boolean | |
| tooltip?: CommonTooltipOption<GeoTooltipFormatterParams> | |
| } | |
| export interface GeoTooltipFormatterParams { | |
| componentType: 'geo' | |
| geoIndex: number | |
| name: string | |
| $vars: ['name'] | |
| } | |
| export interface GeoCommonOptionMixin extends RoamOptionMixin { | |
| // Map name | |
| map: string; | |
| // Aspect is width / height. Inited to be geoJson bbox aspect | |
| // This parameter is used for scale this aspect | |
| aspectScale?: number; | |
| // 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 | |
| // Like: `40` or `'50%'`. | |
| layoutCenter?: (number | string)[]; | |
| // Like: `40` or `'50%'`. | |
| layoutSize?: number | string; | |
| // Define left-top, right-bottom lng/lat coords to control view | |
| // For example, [ [180, 90], [-180, -90] ] | |
| // higher priority than center and zoom | |
| boundingCoords?: number[][]; | |
| nameMap?: NameMap; | |
| nameProperty?: string; | |
| /** | |
| * Use raw projection by default | |
| * Only available for GeoJSON source. | |
| * | |
| * NOTE: `center` needs to be the projected coord if projection is used. | |
| */ | |
| projection?: GeoProjection; | |
| } | |
| export interface GeoOption extends | |
| ComponentOption, | |
| BoxLayoutOptionMixin, | |
| // For lens animation on geo. | |
| AnimationOptionMixin, | |
| GeoCommonOptionMixin, | |
| StatesOptionMixin<GeoStateOption, StatesMixinBase>, GeoStateOption { | |
| mainType?: 'geo'; | |
| show?: boolean; | |
| silent?: boolean; | |
| regions?: RegoinOption[]; | |
| stateAnimation?: AnimationOptionMixin | |
| selectedMode?: 'single' | 'multiple' | boolean | |
| selectedMap?: Dictionary<boolean> | |
| tooltip?: CommonTooltipOption<GeoTooltipFormatterParams> | |
| } | |
| class GeoModel extends ComponentModel<GeoOption> { | |
| 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, | |
| z: 0, | |
| show: true, | |
| left: 'center', | |
| top: 'center', | |
| // 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 | |
| silent: false, | |
| // Map type | |
| map: '', | |
| // Define left-top, right-bottom coords to control view | |
| // For example, [ [180, 90], [-180, -90] ] | |
| boundingCoords: null, | |
| // Default on center of map | |
| center: null, | |
| zoom: 1, | |
| scaleLimit: null, | |
| // selectedMode: false | |
| label: { | |
| show: false, | |
| color: '#000' | |
| }, | |
| itemStyle: { | |
| borderWidth: 0.5, | |
| borderColor: '#444' | |
| // Default color: | |
| // + geoJSON: #eee | |
| // + geoSVG: null (use SVG original `fill`) | |
| // color: '#eee' | |
| }, | |
| emphasis: { | |
| label: { | |
| show: true, | |
| color: 'rgb(100,0,0)' | |
| }, | |
| itemStyle: { | |
| color: 'rgba(255,215,0,0.8)' | |
| } | |
| }, | |
| select: { | |
| label: { | |
| show: true, | |
| color: 'rgb(100,0,0)' | |
| }, | |
| itemStyle: { | |
| color: 'rgba(255,215,0,0.8)' | |
| } | |
| }, | |
| regions: [] | |
| // tooltip: { | |
| // show: false | |
| // } | |
| }; | |
| init(option: GeoOption, parentModel: Model, ecModel: GlobalModel): void { | |
| const source = geoSourceManager.getGeoResource(option.map); | |
| if (source && source.type === 'geoJSON') { | |
| const itemStyle = option.itemStyle = option.itemStyle || {}; | |
| if (!('color' in itemStyle)) { | |
| itemStyle.color = '#eee'; | |
| } | |
| } | |
| this.mergeDefaultAndTheme(option, ecModel); | |
| // Default label emphasis `show` | |
| modelUtil.defaultEmphasis(option, 'label', ['show']); | |
| } | |
| optionUpdated(): void { | |
| const option = this.option; | |
| option.regions = geoCreator.getFilledRegions( | |
| option.regions, option.map, option.nameMap, option.nameProperty | |
| ); | |
| const selectedMap: Dictionary<boolean> = {}; | |
| this._optionModelMap = zrUtil.reduce(option.regions || [], (optionModelMap, regionOpt) => { | |
| const regionName = regionOpt.name; | |
| if (regionName) { | |
| optionModelMap.set(regionName, new Model(regionOpt, this, this.ecModel)); | |
| if (regionOpt.selected) { | |
| selectedMap[regionName] = true; | |
| } | |
| } | |
| return optionModelMap; | |
| }, zrUtil.createHashMap()); | |
| if (!option.selectedMap) { | |
| option.selectedMap = selectedMap; | |
| } | |
| } | |
| /** | |
| * Get model of region. | |
| */ | |
| getRegionModel(name: string): Model<RegoinOption> { | |
| return this._optionModelMap.get(name) || new Model(null, this, this.ecModel); | |
| } | |
| /** | |
| * Format label | |
| * @param name Region name | |
| */ | |
| getFormattedLabel(name: string, status?: DisplayState) { | |
| const regionModel = this.getRegionModel(name); | |
| const formatter = status === 'normal' | |
| ? regionModel.get(['label', 'formatter']) | |
| : regionModel.get(['emphasis', 'label', 'formatter']); | |
| const params = { | |
| name: name | |
| } as GeoLabelFormatterDataParams; | |
| if (zrUtil.isFunction(formatter)) { | |
| params.status = status; | |
| return formatter(params); | |
| } | |
| else if (zrUtil.isString(formatter)) { | |
| return formatter.replace('{a}', name != null ? name : ''); | |
| } | |
| } | |
| setZoom(zoom: number): void { | |
| this.option.zoom = zoom; | |
| } | |
| setCenter(center: number[]): void { | |
| this.option.center = center; | |
| } | |
| // PENGING If selectedMode is null ? | |
| select(name?: string): void { | |
| const option = this.option; | |
| const selectedMode = option.selectedMode; | |
| if (!selectedMode) { | |
| return; | |
| } | |
| if (selectedMode !== 'multiple') { | |
| option.selectedMap = null; | |
| } | |
| const selectedMap = option.selectedMap || (option.selectedMap = {}); | |
| selectedMap[name] = true; | |
| } | |
| unSelect(name?: string): void { | |
| const selectedMap = this.option.selectedMap; | |
| if (selectedMap) { | |
| selectedMap[name] = false; | |
| } | |
| } | |
| toggleSelected(name?: string): void { | |
| this[this.isSelected(name) ? 'unSelect' : 'select'](name); | |
| } | |
| isSelected(name?: string): boolean { | |
| const selectedMap = this.option.selectedMap; | |
| return !!(selectedMap && selectedMap[name]); | |
| } | |
| } | |
| export default GeoModel; |