/** * echarts地图一般投射算法 * modify from GeoMap v0.5.3 https://github.com/x6doooo/GeoMap * * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com) * */ define(function() { function getBbox(json, specialArea) { specialArea = specialArea || {}; if (!json.srcSize) { parseSrcSize(json, specialArea); } return json.srcSize; } function parseSrcSize(json, specialArea) { specialArea = specialArea || {}; convertorParse.xmin = 360; convertorParse.xmax = -360; convertorParse.ymin = 180; convertorParse.ymax = -180; var shapes = json.features; var geometries; var shape; for (var i = 0, len = shapes.length; i < len; i++) { shape = shapes[i]; if (shape.properties.name && specialArea[shape.properties.name]) { continue; } switch (shape.type) { case 'Feature': convertorParse[shape.geometry.type](shape.geometry.coordinates); break; case 'GeometryCollection' : geometries = shape.geometries; for (var j = 0, len2 = geometries.length; j < len2; j++) { convertorParse[geometries[j].type]( geometries[j].coordinates ); } break; } } json.srcSize = { left: convertorParse.xmin.toFixed(4)*1, top: convertorParse.ymin.toFixed(4)*1, width: (convertorParse.xmax - convertorParse.xmin).toFixed(4)*1, height: (convertorParse.ymax - convertorParse.ymin).toFixed(4)*1 }; return json; } var convertor = { //调整俄罗斯东部到地图右侧与俄罗斯相连 formatPoint: function (p) { return [ ((p[0] < -168.5 && p[1] > 63.8) ? p[0] + 360 : p[0]) + 168.5, 90 - p[1] ]; }, makePoint: function (p) { var self = this; var point = self.formatPoint(p); // for cp if (self._bbox.xmin > p[0]) { self._bbox.xmin = p[0]; } if (self._bbox.xmax < p[0]) { self._bbox.xmax = p[0]; } if (self._bbox.ymin > p[1]) { self._bbox.ymin = p[1]; } if (self._bbox.ymax < p[1]) { self._bbox.ymax = p[1]; } var x = (point[0] - convertor.offset.x) * convertor.scale.x + convertor.offset.left; var y = (point[1] - convertor.offset.y) * convertor.scale.y + convertor.offset.top; return [x, y]; }, Point: function (coordinates) { coordinates = this.makePoint(coordinates); return coordinates.join(','); }, LineString: function (coordinates) { var str = ''; var point; for (var i = 0, len = coordinates.length; i < len; i++) { point = convertor.makePoint(coordinates[i]); if (i === 0) { str = 'M' + point.join(','); } else { str = str + 'L' + point.join(','); } } return str; }, Polygon: function (coordinates) { var str = ''; for (var i = 0, len = coordinates.length; i < len; i++) { str = str + convertor.LineString(coordinates[i]) + 'z'; } return str; }, MultiPoint: function (coordinates) { var arr = []; for (var i = 0, len = coordinates.length; i < len; i++) { arr.push(convertor.Point(coordinates[i])); } return arr; }, MultiLineString: function (coordinates) { var str = ''; for (var i = 0, len = coordinates.length; i < len; i++) { str += convertor.LineString(coordinates[i]); } return str; }, MultiPolygon: function (coordinates) { var str = ''; for (var i = 0, len = coordinates.length; i < len; i++) { str += convertor.Polygon(coordinates[i]); } return str; } }; var convertorParse = { formatPoint: convertor.formatPoint, makePoint: function (p) { var self = this; var point = self.formatPoint(p); var x = point[0]; var 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; } }, Point: function (coordinates) { this.makePoint(coordinates); }, LineString: function (coordinates) { for (var i = 0, len = coordinates.length; i < len; i++) { this.makePoint(coordinates[i]); } }, Polygon: function (coordinates) { for (var i = 0, len = coordinates.length; i < len; i++) { this.LineString(coordinates[i]); } }, MultiPoint: function (coordinates) { for (var i = 0, len = coordinates.length; i < len; i++) { this.Point(coordinates[i]); } }, MultiLineString: function (coordinates) { for (var i = 0, len = coordinates.length; i < len; i++) { this.LineString(coordinates[i]); } }, MultiPolygon: function (coordinates) { for (var i = 0, len = coordinates.length; i < len; i++) { this.Polygon(coordinates[i]); } } }; function geoJson2Path(json, transform, specialArea) { specialArea = specialArea || {}; convertor.scale = null; convertor.offset = null; if (!json.srcSize) { parseSrcSize(json, specialArea); } transform.offset = { x: json.srcSize.left, y: json.srcSize.top, left: transform.OffsetLeft || 0, top: transform.OffsetTop || 0 }; convertor.scale = transform.scale; convertor.offset = transform.offset; var shapes = json.features; var geometries; var pathArray = []; var val; var shape; for (var i = 0, len = shapes.length; i < len; i++) { shape = shapes[i]; if (shape.properties.name && specialArea[shape.properties.name]) { // 忽略specialArea continue; } if (shape.type == 'Feature') { pushApath(shape.geometry, shape); } else if (shape.type == 'GeometryCollection') { geometries = shape.geometries; for (var j = 0, len2 = geometries.length; j < len2; j++) { val = geometries[j]; pushApath(val, val); } } } var shapeType; var shapeCoordinates; var str; function pushApath(gm, shape) { shapeType = gm.type; shapeCoordinates = gm.coordinates; convertor._bbox = { xmin: 360, xmax: -360, ymin: 180, ymax: -180 }; str = convertor[shapeType](shapeCoordinates); pathArray.push({ // type: shapeType, path: str, cp: shape.properties.cp ? convertor.makePoint(shape.properties.cp) : convertor.makePoint([ (convertor._bbox.xmin + convertor._bbox.xmax) / 2, (convertor._bbox.ymin + convertor._bbox.ymax) / 2 ]), properties: shape.properties, id: shape.id }); } return pathArray; } /** * 平面坐标转经纬度 * @param {Array} p */ function pos2geo(obj, p) { var x; var y; if (p instanceof Array) { x = p[0] * 1; y = p[1] * 1; } else { x = p.x * 1; y = p.y * 1; } x = x / obj.scale.x + obj.offset.x - 168.5; x = x > 180 ? x - 360 : x; y = 90 - (y / obj.scale.y + obj.offset.y); return [x, y]; } /** * 经纬度转平面坐标 * @param {Array | Object} p */ function geo2pos(obj, p) { convertor.offset = obj.offset; convertor.scale = obj.scale; return p instanceof Array ? convertor.makePoint([p[0] * 1, p[1] * 1]) : convertor.makePoint([p.x * 1, p.y * 1]); } return { getBbox: getBbox, geoJson2Path: geoJson2Path, pos2geo: pos2geo, geo2pos: geo2pos }; });