| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- /*
- * GeoMap v0.4.3
- * https://github.com/x6doooo/GeoMap
- *
- * Copyright 2013 Dx. Yang
- * Released under the MIT license
- */
- (function(){
- var version = "0.4.3"
- var convertor = {
- "xmin": 360,
- "xmax": 0,
- "ymin": 180,
- "ymax": 0,
- /*!Private
- 让阿拉斯加地区在地图右侧显示
- */
- "formatPoint": function(p){
- return [
- (p[0] < -168.5 ? p[0] + 360 : p[0]) + 170,
- 90 - p[1]
- ];
- },
- "makePoint": function(p){
- var self = this,
- point = self.formatPoint(p),
- x = point[0],
- y = point[1];
- if(self.xmin > x) self.xmin = x;
- if(self.xmax < x) self.xmax = x;
- if(self.ymin > y) self.ymin = y;
- if(self.ymax < y) self.ymax = y;
- return [x, y];
- },
- "Point": function(coordinates){
- coordinates = this.makePoint(coordinates);
- return coordinates.join(',');
- },
- "LineString": function(coordinates){
- var str = '',
- self = this,
- i = 0,
- len = coordinates.length,
- point;
- for( ; i < len; i++){
- point = self.makePoint(coordinates[i]);
- if(i == 0){
- str = 'M' + point.join(',');
- }else{
- str = str + 'L' + point.join(',');
- }
- }
- return str;
- },
- "Polygon": function(coordinates){
- var str = '',
- i = 0,
- len = coordinates.length;
- for(; i < len; i++){
- str = str + convertor.LineString(coordinates[i]) + 'z';
- }
- return str;
- },
- "MultiPoint": function(coordinates){
- var arr = [],
- i = 0,
- len = coordinates.length;
- for(; i < len; i++){
- arr.push(convertor.Point(coordinates[i]));
- }
- return arr;
- },
- "MultiLineString": function(coordinates){
- var str = '',
- i = 0,
- len = coordinates.length;
- for(; i < len; i++){
- str += convertor.LineString(coordinates[i]);
- }
- return str;
- },
- "MultiPolygon": function(coordinates){
- var str = '',
- i = 0,
- len = coordinates.length;
- for(; i < len; i++){
- str += convertor.Polygon(coordinates[i]);
- }
- return str;
- }
- };
- var GeoMap = function(cfg){
- var self = this,
- defaultCfg = {
- container: 'body',
- offset: null,
- scale: null,
- mapStyle: {
- 'fill': '#fff',
- 'stroke': '#999',
- 'stroke-width': 0.7
- },
- crossline:{
- enable: false,
- color: '#ccc'
- },
- background:'#fff'
- };
- $.extend(true, defaultCfg, cfg);
- self.container = $(defaultCfg.container);
- if(self.container.length == 0){
- throw new Error('map container is not defined!');
- }
- self.width = defaultCfg.width || self.container.width();
- self.height = defaultCfg.height || self.container.height();
- self.left = self.container.offset().left;
- self.top = self.container.offset().top;
- self.canvas = new Raphael(self.container.get(0), self.width, self.height);
- self.shapes = self.canvas.set();
- self.config = defaultCfg;
- self.paths = null;
- };
- GeoMap.prototype = {
- load: function(json){
- this.paths = this.json2path(json);
- },
- render: function(){
- var self = this,
- shapes = self.shapes,
- paths = self.paths,
- canvas = self.canvas,
- config = self.config,
- style = config.mapStyle,
- offset = config.offset,
- scale = config.scale,
- background = config.background,
- crossline = config.crossline,
- width = self.width,
- height = self.height,
- left = self.left + 5,
- top = self.top + 7,
- mapleft = convertor.xmin,
- maptop = convertor.ymin,
- mapwidth = convertor.xmax - convertor.xmin,
- mapheight = convertor.ymax - convertor.ymin,
- aPath = null, linehead, linex, liney, back, i, len, currentPath;
- if(!scale){
- var temx = width/mapwidth,
- temy = height/mapheight;
- temx > temy ? temx = temy : temy = temx;
- temx = temy * 0.73;
- scale = {
- x: temx,
- y: temy
- };
- }
- if(!offset){
- offset = {
- x: mapleft,
- y: maptop
- };
- }
- back = canvas.rect(mapleft, maptop, mapwidth, mapheight).scale(scale.x, scale.y, 0, 0).attr({
- 'fill': background, 'stroke-width': 0
- });
- linehead = 'M' + (mapleft) + ',' + (maptop);
- linex = linehead + 'H' + convertor.xmax * scale.x;
- liney = linehead + 'V' + convertor.ymax * scale.y;
- self.crosslineX = canvas.path(linex).attr({'stroke': crossline.color, 'stroke-width': '1px'}).hide();
- self.crosslineY = canvas.path(liney).attr({'stroke': crossline.color, 'stroke-width': '1px'}).hide();
- for(i = 0, len = paths.length; i < len; i++){
- currentPath = paths[i];
- if(currentPath.type == 'point' || currentPath.type == 'MultiPoint'){
- //TODO
- }else{
- aPath = canvas.path(currentPath.path).data({'properties': currentPath.properties, 'id': currentPath.id});
- }
- shapes.push(aPath);
- }
- canvas.setViewBox(offset.x, offset.y, width, height, false);
- shapes.attr(style).scale(scale.x, scale.y, mapleft, maptop);
- //TODO: crossline的位置计算,由于要做一点偏移,所以偏移量要考虑到缩放问题,类似getGeoPosition方法,计算出图上偏移的实际值
- if(crossline.enable === true){
- shapes.mouseover(function(){
- showCrossLine();
- }).mousemove(function(e){
- moveCrossLine(e);
- }).mouseout(function(){
- hideCrossLine();
- });
- back.mouseover(function(){
- showCrossLine();
- }).mousemove(function(e){
- moveCrossLine(e);
- }).mouseout(function(){
- hideCrossLine();
- });
- }
- function showCrossLine(){
- self.crosslineX.toFront().show();
- self.crosslineY.toFront().show();
- }
- function moveCrossLine(e){
- var pos = getEventPos(e);
- self.crosslineX.transform('T0,'+pos.y);
- self.crosslineY.transform('T'+ pos.x + ',0');
- }
- function hideCrossLine(){
- self.crosslineX.hide();
- self.crosslineY.hide();
- }
- function getEventPos(e){
- return {
- x: parseInt(e.pageX - left) + 0.4,
- y: parseInt(e.pageY - top) + 0.4
- };
- }
- },
- /*!
- 将平面上的一个点的坐标,转换成实际经纬度坐标
- */
- getGeoPosition: function(p){
- var x1 = p[0],
- y1 = p[1],
- m = this.shapes[0].matrix,
- x,
- y;
- a = m.a;
- b = m.b;
- c = m.c;
- d = m.d;
- e = m.e;
- f = m.f;
- y = (y1 - f - x1 / a * b + e / a * b) / (d - c / a * b);
- x = (x1 - e - y * c) / a;
- y = 90 - y;
- x = x - 170;
- x = x > 180 ? x - 360 : x;
- return [x, y];
- },
- setPoint: function(p){
- // 点的默认样式
- var self = this,
- a = {
- "x":0,
- "y":0,
- "r":1,
- "opacity":0.5,
- "fill": "#238CC3",
- "stroke": "#238CC3",
- "stroke-width": 0,
- "stroke-linejoin": "round"
- },
- matrixTrans = self.shapes[0].matrix;
- $.extend(true, a, p);
- p = convertor.makePoint([a.x, a.y]);
- //通过matrix去计算点变换后的坐标
- p[0] = matrixTrans.x(p[0], p[1]);
- p[1] = matrixTrans.y(p[0], p[1]);
- self.getGeoPosition(p);
- a.x = p[0];
- a.y = p[1];
- c = self.canvas.circle(p[0], p[1], a.r).attr(a);
- return c;
- },
- json2path: function(json){
- var self = this,
- shapes = json.features,
- shapeType,
- shapeCoordinates,
- str,
- geometries,
- pathArray = [],
- i, j,
- len, len2,
- val,
- shape;
- convertor.xmin = 360;
- convertor.xmax = 0;
- convertor.ymin = 180;
- convertor.ymax = 0;
- for(i = 0, len = shapes.length; i < len; i++){
- shape = shapes[i];
- if(shape.type == 'Feature'){
- pushApath(shape.geometry, shape);
- }else if(shape.type = 'GeometryCollection'){
- geometries = shape.geometries;
- for(j = 0, len2 = geometries.length; j < len2; j++){
- val = geometries[j];
- pushApath(val, val);
- }
- }
- }
- function pushApath(gm, shape){
- shapeType = gm.type;
- shapeCoordinates = gm.coordinates;
- str = convertor[shapeType](shapeCoordinates);
- pathArray.push({
- type: shapeType,
- path: str,
- properties: shape.properties,
- id: shape.id
- });
- }
- return pathArray;
- }
- };
- GeoMap.version = version;
- this.GeoMap = GeoMap;
- })();
|