geomap-0.3.1.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * GeoMap v0.3
  3. * https://github.com/x6doooo/GeoMap
  4. *
  5. * Copyright 2013 Dx. Yang
  6. * Released under the MIT license
  7. */
  8. /*
  9. *
  10. * TODO: 将图上的坐标转换成实际经纬度
  11. *
  12. * */
  13. (function($){
  14. var convertor = {
  15. "xmin": 360,
  16. "xmax": 0,
  17. "ymin": 180,
  18. "ymax": 0,
  19. "formatPoint": function(p){
  20. return [(p[0] < -168.5 ? p[0] + 360 : p[0]) + 170, 90 - p[1]];
  21. },
  22. "makePoint": function(p){
  23. var self = this,
  24. point = self.formatPoint(p),
  25. x = point[0],
  26. y = point[1];
  27. if(self.xmin > x) self.xmin = x;
  28. if(self.xmax < x) self.xmax = x;
  29. if(self.ymin > y) self.ymin = y;
  30. if(self.ymax < y) self.ymax = y;
  31. return [x, y];
  32. },
  33. "Point": function(coordinates){
  34. coordinates = this.makePoint(coordinates);
  35. return coordinates.join(',');
  36. },
  37. "LineString": function(coordinates){
  38. var str = '',
  39. self = this,
  40. i = 0,
  41. len = coordinates.length,
  42. point;
  43. for( ; i < len; i++){
  44. point = self.makePoint(coordinates[i]);
  45. if(i == 0){
  46. str = 'M' + point.join(',');
  47. }else{
  48. str = str + 'L' + point.join(',');
  49. }
  50. }
  51. return str;
  52. },
  53. "Polygon": function(coordinates){
  54. var str = '',
  55. i = 0,
  56. len = coordinates.length;
  57. for(; i < len; i++){
  58. str = str + convertor.LineString(coordinates[i]) + 'z';
  59. }
  60. return str;
  61. },
  62. "MultiPoint": function(coordinates){
  63. var arr = [],
  64. i = 0,
  65. len = coordinates.length;
  66. for(; i < len; i++){
  67. arr.push(convertor.Point(coordinates[i]));
  68. }
  69. return arr;
  70. },
  71. "MultiLineString": function(coordinates){
  72. var str = '',
  73. i = 0,
  74. len = coordinates.length;
  75. for(; i < len; i++){
  76. str += convertor.LineString(coordinates[i]);
  77. }
  78. return str;
  79. },
  80. "MultiPolygon": function(coordinates){
  81. var str = '',
  82. i = 0,
  83. len = coordinates.length;
  84. for(; i < len; i++){
  85. str += convertor.Polygon(coordinates[i]);
  86. }
  87. return str;
  88. }
  89. },
  90. GeoMap = function(cfg){
  91. var self = this,
  92. defaultCfg = {
  93. container: 'body',
  94. offset: null,
  95. scale: null,
  96. mapStyle: {
  97. 'fill': '#fff',
  98. 'stroke': '#999',
  99. 'stroke-width': 0.7
  100. },
  101. crossline:{
  102. enable: true,
  103. color: '#ccc'
  104. },
  105. background:'#fff'
  106. };
  107. $.extend(true, defaultCfg, cfg);
  108. self.container = $(defaultCfg.container);
  109. self.width = defaultCfg.width || self.container.width();
  110. self.height = defaultCfg.height || self.container.height();
  111. self.left = self.container.offset().left;
  112. self.top = self.container.offset().top;
  113. self.canvas = new Raphael(self.container.get(0), self.width, self.height);
  114. self.shapes = self.canvas.set();
  115. self.config = defaultCfg;
  116. self.paths = null;
  117. };
  118. GeoMap.prototype = {
  119. load: function(json){
  120. this.paths = this.json2path(json);
  121. },
  122. render: function(){
  123. var self = this,
  124. shapes = self.shapes,
  125. paths = self.paths,
  126. canvas = self.canvas,
  127. config = self.config,
  128. style = config.mapStyle,
  129. offset = config.offset,
  130. scale = config.scale,
  131. background = config.background,
  132. crossline = config.crossline,
  133. width = self.width,
  134. height = self.height,
  135. left = self.left + 5,
  136. top = self.top + 7,
  137. mapleft = convertor.xmin,
  138. maptop = convertor.ymin,
  139. mapwidth = convertor.xmax - convertor.xmin,
  140. mapheight = convertor.ymax - convertor.ymin,
  141. aPath = null, linehead, linex, liney, back, idx, len, currentPath;
  142. if(!scale){
  143. var temx = width/mapwidth,
  144. temy = height/mapheight;
  145. temx > temy ? temx = temy : temy = temx;
  146. temx = temy * 0.73;
  147. scale = {
  148. x: temx,
  149. y: temy
  150. };
  151. }
  152. if(!offset){
  153. offset = {
  154. x: mapleft,
  155. y: maptop
  156. };
  157. }
  158. back = canvas.rect(mapleft, maptop, mapwidth, mapheight).scale(scale.x, scale.y, 0, 0).attr({
  159. 'fill': background, 'stroke-width': 0
  160. });
  161. linehead = 'M' + (mapleft) + ',' + (maptop);
  162. linex = linehead + 'H' + convertor.xmax * scale.x;
  163. liney = linehead + 'V' + convertor.ymax * scale.y;
  164. self.crosslineX = canvas.path(linex).attr({'stroke': crossline.color, 'stroke-width': '1px'}).hide();
  165. self.crosslineY = canvas.path(liney).attr({'stroke': crossline.color, 'stroke-width': '1px'}).hide();
  166. for(i = 0, len = paths.length; i < len; i++){
  167. currentPath = paths[i];
  168. if(currentPath.type == 'point' || currentPath.type == 'MultiPoint'){
  169. //TODO
  170. }else{
  171. aPath = canvas.path(currentPath.path).data({'properties': currentPath.properties, 'id': currentPath.id});
  172. }
  173. shapes.push(aPath);
  174. }
  175. canvas.setViewBox(offset.x, offset.y, width, height, false);
  176. shapes.attr(style).scale(scale.x, scale.y, mapleft, maptop);
  177. if(crossline.enable === true){
  178. shapes.mouseover(function(){
  179. showCrossLine();
  180. }).mousemove(function(e){
  181. moveCrossLine(e);
  182. }).mouseout(function(){
  183. hideCrossLine();
  184. });
  185. back.mouseover(function(){
  186. showCrossLine();
  187. }).mousemove(function(e){
  188. moveCrossLine(e);
  189. }).mouseout(function(){
  190. hideCrossLine();
  191. });
  192. }
  193. function showCrossLine(){
  194. self.crosslineX.toFront().show();
  195. self.crosslineY.toFront().show();
  196. }
  197. function moveCrossLine(e){
  198. var pos = getEventPos(e);
  199. self.crosslineX.transform('T0,'+pos.y);
  200. self.crosslineY.transform('T'+ pos.x + ',0');
  201. }
  202. function hideCrossLine(){
  203. self.crosslineX.hide();
  204. self.crosslineY.hide();
  205. }
  206. function getEventPos(e){
  207. return {
  208. x: parseInt(e.pageX - left) + 0.4,
  209. y: parseInt(e.pageY - top) + 0.4
  210. };
  211. }
  212. },
  213. setPoint: function(p){
  214. // 点的默认样式
  215. var self = this,
  216. a = {
  217. "x":0,
  218. "y":0,
  219. "r":1,
  220. "opacity":0.5,
  221. "fill": "#238CC3",
  222. "stroke": "#238CC3",
  223. "stroke-width": 0,
  224. "stroke-linejoin": "round"
  225. },
  226. matrixTrans = self.shapes[0].matrix;
  227. $.extend(true, a, p);
  228. p = convertor.makePoint([a.x, a.y]);
  229. //通过matrix去计算点变换后的坐标
  230. p[0] = matrixTrans.x(p[0], p[1]);
  231. p[1] = matrixTrans.y(p[0], p[1]);
  232. a.x = p[0];
  233. a.y = p[1];
  234. c = self.canvas.circle(p[0], p[1], a.r).attr(a);
  235. return c;
  236. },
  237. json2path: function(json){
  238. var self = this,
  239. shapes = json.features,
  240. shapeType,
  241. shapeCoordinates,
  242. str,
  243. geometries,
  244. pathArray = [],
  245. i, j,
  246. len, len2,
  247. val,
  248. shape;
  249. convertor.xmin = 360;
  250. convertor.xmax = 0;
  251. convertor.ymin = 180;
  252. convertor.ymax = 0;
  253. for(i = 0, len = shapes.length; i < len; i++){
  254. shape = shapes[i];
  255. if(shape.type == 'Feature'){
  256. pushApath(shape.geometry, shape);
  257. }else if(shape.type = 'GeometryCollection'){
  258. geometries = shape.geometries;
  259. for(j = 0, len2 = geometries.length; j < len2; j++){
  260. val = geometries[j];
  261. pushApath(val, val);
  262. }
  263. }
  264. }
  265. function pushApath(gm, shape){
  266. shapeType = gm.type;
  267. shapeCoordinates = gm.coordinates;
  268. str = convertor[shapeType](shapeCoordinates);
  269. pathArray.push({
  270. type: shapeType,
  271. path: str,
  272. properties: shape.properties,
  273. id: shape.id
  274. });
  275. }
  276. return pathArray;
  277. }
  278. };
  279. window.GeoMap = GeoMap;
  280. })(jQuery);