/*
|
* 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
|
} from '../../util/types';
|
import { NameMap } from './geoTypes';
|
import GlobalModel from '../../model/Global';
|
import geoSourceManager from './geoSourceManager';
|
|
|
export interface GeoItemStyleOption extends ItemStyleOption {
|
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> {
|
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 wan't to put map in a fixed size box with right aspect ratio
|
// This two properties may more conveninet
|
// Like: `40` or `'50%'`.
|
layoutCenter?: (number | string)[];
|
// Like: `40` or `'50%'`.
|
layoutSize?: number | string;
|
|
// Define left-top, right-bottom coords to control view
|
// For example, [ [180, 90], [-180, -90] ]
|
// higher priority than center and zoom
|
boundingCoords?: number[][];
|
|
nameMap?: NameMap;
|
nameProperty?: string;
|
}
|
|
export interface GeoOption extends
|
ComponentOption,
|
BoxLayoutOptionMixin,
|
// For lens animation on geo.
|
AnimationOptionMixin,
|
GeoCommonOptionMixin,
|
StatesOptionMixin<GeoStateOption>, 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 wan't to put map in a fixed size box with right aspect ratio
|
// This two properties may more conveninet
|
// 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 (typeof formatter === 'function') {
|
params.status = status;
|
return formatter(params);
|
}
|
else if (typeof formatter === 'string') {
|
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;
|