Geo.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. var zrUtil = require("zrender/lib/core/util");
  2. var BoundingRect = require("zrender/lib/core/BoundingRect");
  3. var parseGeoJson = require("./parseGeoJson");
  4. var View = require("../View");
  5. var fixNanhai = require("./fix/nanhai");
  6. var fixTextCoord = require("./fix/textCoord");
  7. var fixGeoCoord = require("./fix/geoCoord");
  8. var fixDiaoyuIsland = require("./fix/diaoyuIsland");
  9. // Geo fix functions
  10. var geoFixFuncs = [fixNanhai, fixTextCoord, fixGeoCoord, fixDiaoyuIsland];
  11. /**
  12. * [Geo description]
  13. * @param {string} name Geo name
  14. * @param {string} map Map type
  15. * @param {Object} geoJson
  16. * @param {Object} [specialAreas]
  17. * Specify the positioned areas by left, top, width, height
  18. * @param {Object.<string, string>} [nameMap]
  19. * Specify name alias
  20. */
  21. function Geo(name, map, geoJson, specialAreas, nameMap) {
  22. View.call(this, name);
  23. /**
  24. * Map type
  25. * @type {string}
  26. */
  27. this.map = map;
  28. this._nameCoordMap = zrUtil.createHashMap();
  29. this.loadGeoJson(geoJson, specialAreas, nameMap);
  30. }
  31. Geo.prototype = {
  32. constructor: Geo,
  33. type: 'geo',
  34. /**
  35. * @param {Array.<string>}
  36. * @readOnly
  37. */
  38. dimensions: ['lng', 'lat'],
  39. /**
  40. * If contain given lng,lat coord
  41. * @param {Array.<number>}
  42. * @readOnly
  43. */
  44. containCoord: function (coord) {
  45. var regions = this.regions;
  46. for (var i = 0; i < regions.length; i++) {
  47. if (regions[i].contain(coord)) {
  48. return true;
  49. }
  50. }
  51. return false;
  52. },
  53. /**
  54. * @param {Object} geoJson
  55. * @param {Object} [specialAreas]
  56. * Specify the positioned areas by left, top, width, height
  57. * @param {Object.<string, string>} [nameMap]
  58. * Specify name alias
  59. */
  60. loadGeoJson: function (geoJson, specialAreas, nameMap) {
  61. // https://jsperf.com/try-catch-performance-overhead
  62. try {
  63. this.regions = geoJson ? parseGeoJson(geoJson) : [];
  64. } catch (e) {
  65. throw 'Invalid geoJson format\n' + e.message;
  66. }
  67. specialAreas = specialAreas || {};
  68. nameMap = nameMap || {};
  69. var regions = this.regions;
  70. var regionsMap = zrUtil.createHashMap();
  71. for (var i = 0; i < regions.length; i++) {
  72. var regionName = regions[i].name; // Try use the alias in nameMap
  73. regionName = nameMap.hasOwnProperty(regionName) ? nameMap[regionName] : regionName;
  74. regions[i].name = regionName;
  75. regionsMap.set(regionName, regions[i]); // Add geoJson
  76. this.addGeoCoord(regionName, regions[i].center); // Some area like Alaska in USA map needs to be tansformed
  77. // to look better
  78. var specialArea = specialAreas[regionName];
  79. if (specialArea) {
  80. regions[i].transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);
  81. }
  82. }
  83. this._regionsMap = regionsMap;
  84. this._rect = null;
  85. zrUtil.each(geoFixFuncs, function (fixFunc) {
  86. fixFunc(this);
  87. }, this);
  88. },
  89. // Overwrite
  90. transformTo: function (x, y, width, height) {
  91. var rect = this.getBoundingRect();
  92. rect = rect.clone(); // Longitute is inverted
  93. rect.y = -rect.y - rect.height;
  94. var viewTransform = this._viewTransform;
  95. viewTransform.transform = rect.calculateTransform(new BoundingRect(x, y, width, height));
  96. viewTransform.decomposeTransform();
  97. var scale = viewTransform.scale;
  98. scale[1] = -scale[1];
  99. viewTransform.updateTransform();
  100. this._updateTransform();
  101. },
  102. /**
  103. * @param {string} name
  104. * @return {module:echarts/coord/geo/Region}
  105. */
  106. getRegion: function (name) {
  107. return this._regionsMap.get(name);
  108. },
  109. getRegionByCoord: function (coord) {
  110. var regions = this.regions;
  111. for (var i = 0; i < regions.length; i++) {
  112. if (regions[i].contain(coord)) {
  113. return regions[i];
  114. }
  115. }
  116. },
  117. /**
  118. * Add geoCoord for indexing by name
  119. * @param {string} name
  120. * @param {Array.<number>} geoCoord
  121. */
  122. addGeoCoord: function (name, geoCoord) {
  123. this._nameCoordMap.set(name, geoCoord);
  124. },
  125. /**
  126. * Get geoCoord by name
  127. * @param {string} name
  128. * @return {Array.<number>}
  129. */
  130. getGeoCoord: function (name) {
  131. return this._nameCoordMap.get(name);
  132. },
  133. // Overwrite
  134. getBoundingRect: function () {
  135. if (this._rect) {
  136. return this._rect;
  137. }
  138. var rect;
  139. var regions = this.regions;
  140. for (var i = 0; i < regions.length; i++) {
  141. var regionRect = regions[i].getBoundingRect();
  142. rect = rect || regionRect.clone();
  143. rect.union(regionRect);
  144. } // FIXME Always return new ?
  145. return this._rect = rect || new BoundingRect(0, 0, 0, 0);
  146. },
  147. /**
  148. * @param {string|Array.<number>} data
  149. * @return {Array.<number>}
  150. */
  151. dataToPoint: function (data) {
  152. if (typeof data === 'string') {
  153. // Map area name to geoCoord
  154. data = this.getGeoCoord(data);
  155. }
  156. if (data) {
  157. return View.prototype.dataToPoint.call(this, data);
  158. }
  159. },
  160. /**
  161. * @inheritDoc
  162. */
  163. convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
  164. /**
  165. * @inheritDoc
  166. */
  167. convertFromPixel: zrUtil.curry(doConvert, 'pointToData')
  168. };
  169. zrUtil.mixin(Geo, View);
  170. function doConvert(methodName, ecModel, finder, value) {
  171. var geoModel = finder.geoModel;
  172. var seriesModel = finder.seriesModel;
  173. var coordSys = geoModel ? geoModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem // For map.
  174. || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem : null;
  175. return coordSys === this ? coordSys[methodName](value) : null;
  176. }
  177. var _default = Geo;
  178. module.exports = _default;