var zrUtil = require("zrender/lib/core/util"); var BoundingRect = require("zrender/lib/core/BoundingRect"); var parseGeoJson = require("./parseGeoJson"); var View = require("../View"); var fixNanhai = require("./fix/nanhai"); var fixTextCoord = require("./fix/textCoord"); var fixGeoCoord = require("./fix/geoCoord"); var fixDiaoyuIsland = require("./fix/diaoyuIsland"); /* * 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. */ // Geo fix functions var geoFixFuncs = [fixNanhai, fixTextCoord, fixGeoCoord, fixDiaoyuIsland]; /** * [Geo description] * @param {string} name Geo name * @param {string} map Map type * @param {Object} geoJson * @param {Object} [specialAreas] * Specify the positioned areas by left, top, width, height * @param {Object.} [nameMap] * Specify name alias */ function Geo(name, map, geoJson, specialAreas, nameMap) { View.call(this, name); /** * Map type * @type {string} */ this.map = map; this._nameCoordMap = zrUtil.createHashMap(); this.loadGeoJson(geoJson, specialAreas, nameMap); } Geo.prototype = { constructor: Geo, type: 'geo', /** * @param {Array.} * @readOnly */ dimensions: ['lng', 'lat'], /** * If contain given lng,lat coord * @param {Array.} * @readOnly */ containCoord: function (coord) { var regions = this.regions; for (var i = 0; i < regions.length; i++) { if (regions[i].contain(coord)) { return true; } } return false; }, /** * @param {Object} geoJson * @param {Object} [specialAreas] * Specify the positioned areas by left, top, width, height * @param {Object.} [nameMap] * Specify name alias */ loadGeoJson: function (geoJson, specialAreas, nameMap) { // https://jsperf.com/try-catch-performance-overhead try { this.regions = geoJson ? parseGeoJson(geoJson) : []; } catch (e) { throw 'Invalid geoJson format\n' + e.message; } specialAreas = specialAreas || {}; nameMap = nameMap || {}; var regions = this.regions; var regionsMap = zrUtil.createHashMap(); for (var i = 0; i < regions.length; i++) { var regionName = regions[i].name; // Try use the alias in nameMap regionName = nameMap.hasOwnProperty(regionName) ? nameMap[regionName] : regionName; regions[i].name = regionName; regionsMap.set(regionName, regions[i]); // Add geoJson this.addGeoCoord(regionName, regions[i].center); // Some area like Alaska in USA map needs to be tansformed // to look better var specialArea = specialAreas[regionName]; if (specialArea) { regions[i].transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height); } } this._regionsMap = regionsMap; this._rect = null; zrUtil.each(geoFixFuncs, function (fixFunc) { fixFunc(this); }, this); }, // Overwrite transformTo: function (x, y, width, height) { var rect = this.getBoundingRect(); rect = rect.clone(); // Longitute is inverted rect.y = -rect.y - rect.height; var rawTransformable = this._rawTransformable; rawTransformable.transform = rect.calculateTransform(new BoundingRect(x, y, width, height)); rawTransformable.decomposeTransform(); var scale = rawTransformable.scale; scale[1] = -scale[1]; rawTransformable.updateTransform(); this._updateTransform(); }, /** * @param {string} name * @return {module:echarts/coord/geo/Region} */ getRegion: function (name) { return this._regionsMap.get(name); }, getRegionByCoord: function (coord) { 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.} geoCoord */ addGeoCoord: function (name, geoCoord) { this._nameCoordMap.set(name, geoCoord); }, /** * Get geoCoord by name * @param {string} name * @return {Array.} */ getGeoCoord: function (name) { return this._nameCoordMap.get(name); }, // Overwrite getBoundingRect: function () { if (this._rect) { return this._rect; } var rect; var regions = this.regions; for (var i = 0; i < regions.length; i++) { var regionRect = regions[i].getBoundingRect(); rect = rect || regionRect.clone(); rect.union(regionRect); } // FIXME Always return new ? return this._rect = rect || new BoundingRect(0, 0, 0, 0); }, /** * @param {string|Array.} data * @param {boolean} noRoam * @param {Array.} [out] * @return {Array.} */ dataToPoint: function (data, noRoam, out) { if (typeof data === 'string') { // Map area name to geoCoord data = this.getGeoCoord(data); } if (data) { return View.prototype.dataToPoint.call(this, data, noRoam, out); } }, /** * @inheritDoc */ convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'), /** * @inheritDoc */ convertFromPixel: zrUtil.curry(doConvert, 'pointToData') }; zrUtil.mixin(Geo, View); function doConvert(methodName, ecModel, finder, value) { var geoModel = finder.geoModel; var seriesModel = finder.seriesModel; var coordSys = geoModel ? geoModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem // For map. || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem : null; return coordSys === this ? coordSys[methodName](value) : null; } var _default = Geo; module.exports = _default;