Openlayers加载腾讯、高德、天地图
之前加载的百度地图,偏移较大,一直没有再测试,于是将腾讯、高德、天地图的整理一下,方便查看。
腾讯js代码:
1 OpenLayers.Layer.QQ = OpenLayers.Class(OpenLayers.Layer.TileCache, { 2 sateTiles: !1, 3 initialize: function(a, b, c) { 4 var d = OpenLayers.Util.extend({ 5 format: "image/png", 6 isBaseLayer: !0 7 }, 8 c); 9 OpenLayers.Layer.TileCache.prototype.initialize.apply(this, [a, b, {}, 10 d]), 11 this.extension = this.format.split("/")[1].toLowerCase(), 12 this.extension = "jpg" == this.extension ? "jpeg": this.extension, 13 this.transitionEffect = "resize", 14 this.buffer = 0 15 }, 16 getURL: function(a) { 17 var b = this.map.getResolution(), 18 c = this.map.getMaxExtent(), 19 d = this.tileSize, 20 e = this.map.zoom, 21 f = Math.round((a.left - c.left) / (b * d.w)), 22 g = Math.round((c.top - a.top) / (b * d.h)), 23 h = new Array(0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 7, 0, 7, 0, 15, 0, 15, 0, 31, 0, 31, 0, 63, 4, 59, 0, 127, 12, 115, 0, 225, 28, 227, 356, 455, 150, 259, 720, 899, 320, 469, 1440, 1799, 650, 929, 2880, 3589, 1200, 2069, 5760, 7179, 2550, 3709, 11520, 14349, 5100, 7999, 23060, 28689, 10710, 15429, 46120, 57369, 20290, 29849, 89990, 124729, 41430, 60689, 184228, 229827, 84169, 128886), 24 i = 4 * e, 25 j = h[i++], 26 k = h[i++], 27 l = h[i++], 28 h = h[i], 29 m = this.sateTiles ? ".jpg": ".png"; 30 if (f >= j && k >= f && g >= l && h >= g) { 31 g = Math.pow(2, e) - 1 - g; 32 var n = 'z=' + e + '&x=' + f + '&y=' + g + '&type=vector&style=0&v=1.1.1' 33 } 34 var o = this.url; 35 return OpenLayers.Util.isArray(o) && n && (o = this.selectUrl(n, o)), 36 o + n 37 }, 38 clone: function(a) { 39 return null == a && (a = new OpenLayers.Layer.QQ(this.name, this.url, this.options)), 40 a = OpenLayers.Layer.TileCache.prototype.clone.apply(this, [a]) 41 }, 42 CLASS_NAME: "OpenLayers.Layer.QQ" 43 });
QQ地图的服务地址换了,这里记下以前的地址(屏蔽的代码)和现在的地址。
1 //QQ地图 2 map.addLayer( 3 new OpenLayers.Layer.QQ("QQ地图", 4 [ 5 //"http://p0.map.soso.com/maptilesv2/", 6 //"http://p1.map.soso.com/maptilesv2/", 7 //"http://p2.map.soso.com/maptilesv2/", 8 //"http://p3.map.soso.com/maptilesv2/" 9 'http://rt0.map.gtimg.com/realtimerender?', 10 'http://rt1.map.gtimg.com/realtimerender?', 11 'http://rt2.map.gtimg.com/realtimerender?', 12 'http://rt3.map.gtimg.com/realtimerender?' 13 ], 14 { 15 sateTiles: false 16 } 17 ) 18 );
QQ地图和高德地图为火星坐标,纠正坐标可以用同一套方法,网上有js文件可以下载。
高德地图:
1 OpenLayers.Layer.Gaode = OpenLayers.Class(OpenLayers.Layer.TileCache, { 2 initialize: function (name, url, options) { 3 var tempoptions = OpenLayers.Util.extend({ 4 'format': 'image/png', 5 isBaseLayer: true 6 }, options); 7 OpenLayers.Layer.TileCache.prototype.initialize.apply(this, [name, url, {}, tempoptions]); 8 this.extension = this.format.split('/')[1].toLowerCase(); 9 this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension; 10 this.transitionEffect = "resize"; 11 this.buffer = 0; 12 }, 13 getURL: function (bounds) { 14 var retUrl = this.url+"lang=zh_cn&size=1&scale=1&style=8&"; 15 var res = this.map.getResolution(); 16 var bbox = this.map.getMaxExtent(); 17 var size = this.tileSize; 18 //计算列号 19 var tileX = Math.round((bounds.left - bbox.left) / (res * size.w)); 20 //计算行号 21 var tileY = Math.round((bbox.top - bounds.top) / (res * size.h)); 22 //当前的等级 23 debugger; 24 var tileZ = this.map.zoom-1; 25 if (tileX < 0) tileX = tileX + Math.round(bbox.getWidth() / bounds.getWidth()); 26 if (tileY < 0) tileY = tileY + Math.round(bbox.getHeight() / bounds.getHeight()); 27 //tileY = (Math.pow(2, tileZ) - 1 - tileY); 28 //tileY = Math.pow(2, tileZ)-tileY+Math.pow(2,this.map.zoom-3); 29 tileY = 1+tileY+Math.pow(2,this.map.zoom-3); 30 console.log(tileY+" =tileY"); 31 return retUrl+"x="+tileX+"&y="+tileY+"&z="+this.map.zoom; 32 }, 33 34 clone: function (obj) { 35 if (obj == null) { 36 obj = new OpenLayers.Layer.Gaode(this.name, this.url, this.options); 37 } 38 obj = OpenLayers.Layer.TileCache.prototype.clone.apply(this, [obj]); 39 return obj; 40 }, 41 CLASS_NAME: "OpenLayers.Layer.Gaode" 42 });
加载高德地图的地址,其中屏蔽的地址是下载到本机的离线地图使用的瓦片地址,其他离线地图也类似。
1 //高德地图 2 var vecLayer = new OpenLayers.Layer.XYZ("高德地图", [ 3 "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x=${x}&y=${y}&z=${z}", 4 "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x=${x}&y=${y}&z=${z}", 5 "http://webrd03.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x=${x}&y=${y}&z=${z}", 6 "http://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x=${x}&y=${y}&z=${z}" 7 //"data/roadmap/${z}/${x}/${y}.png" 8 ], { 9 isBaseLayer: true, 10 visibility: true, 11 displayInLayerSwitcher: true 12 }); 13 map.addLayer(vecLayer);
天地图可以直接使用,WGS84坐标,除了长得丑了点以外,其他都还好。
1 OpenLayers.Layer.TDT = OpenLayers.Class(OpenLayers.Layer.Grid, { 2 3 mapType: null, 4 mirrorUrls: null, 5 topLevel: null, 6 bottomLevel: null, 7 8 topLevelIndex: 0, 9 bottomLevelIndex: 20, 10 topTileFromX: -180, 11 topTileFromY: 90, 12 topTileToX: 180, 13 topTileToY: -270, 14 15 isBaseLayer: true, 16 17 initialize: function (name,options) { 18 19 options.topLevel = options.topLevel ? options.topLevel : this.topLevelIndex; 20 options.bottomLevel = options.bottomLevel ? options.bottomLevel : this.bottomLevelIndex; 21 options.maxResolution = this.getResolutionForLevel(options.topLevel); 22 options.minResolution = this.getResolutionForLevel(options.bottomLevel); 23 24 var newArguments = [name, {}, {}, options]; 25 OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments); 26 }, 27 28 clone: function (obj) { 29 30 if (obj == null) { 31 obj = new OpenLayers.Layer.TDTLayer(this.name, this.url, this.options); 32 } 33 34 obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]); 35 36 return obj; 37 }, 38 39 getURL: function (bounds) { 40 var level = this.getLevelForResolution(this.map.getResolution()); 41 var coef = 360 / Math.pow(2, level); 42 var x_num = this.topTileFromX < this.topTileToX ? Math.round((bounds.left - this.topTileFromX) / coef) : Math.round((this.topTileFromX - bounds.right) / coef); 43 var y_num = this.topTileFromY < this.topTileToY ? Math.round((bounds.bottom - this.topTileFromY) / coef) : Math.round((this.topTileFromY - bounds.top) / coef); 44 45 switch(level){ 46 case 8: 47 url="http://tile6.tianditu.com/DataServer?T=tdt_vip_img_2_10_120627"; 48 break 49 case 9: 50 url="http://tile5.tianditu.com/DataServer?T=tdt_vip_img_2_10_120627"; 51 break 52 case 10: 53 url="http://tile5.tianditu.com/DataServer?T=tdt_vip_img_2_10_120627"; 54 break 55 case 11: 56 url:"http://tile1.tianditu.com/DataServer?T=E11N"; 57 break 58 case 12: 59 url="http://tile6.tianditu.com/DataServer?T=E12N"; 60 break 61 case 13: 62 url="http://tile3.tianditu.com/DataServer?T=E13N"; 63 break 64 case 14: 65 url="http://tile2.tianditu.com/DataServer?T=E14N"; 66 break 67 case 15: 68 url="http://tile5.tianditu.com/DataServer?T=tdt_vip_img_120627_dyd" 69 break 70 case 16: 71 url="http://tile2.tianditu.com/DataServer?T=tdt_vip_img_120627_dyd"; 72 break 73 case 17: 74 url="http://tile1.tianditu.com/DataServer?T=tdt_vip_img_120627_dyd"; 75 break 76 case 18: 77 url="http://tile0.tianditu.com/DataServer?T=tdt_vip_img_120627_dyd"; 78 break 79 } 80 81 return this.getFullRequestString({ T: null, X: x_num, Y: y_num, L: level }, url); 82 }, 83 selectUrl: function (a, b) { return b[a % b.length] }, 84 getLevelForResolution: function (res) { 85 var ratio = this.getMaxResolution() / res; 86 if (ratio < 1) return 0; 87 for (var level = 0; ratio / 2 >= 1; ) 88 { level++; ratio /= 2; } 89 return level; 90 }, 91 getResolutionForLevel: function (level) { 92 return 360 / 256 / Math.pow(2, level); 93 }, 94 getMaxResolution: function () { 95 return this.getResolutionForLevel(this.topLevelIndex) 96 }, 97 getMinResolution: function () { 98 return this.getResolutionForLevel(this.bottomLevelIndex) 99 }, 100 addTile: function (bounds, position) { 101 var url = this.getURL(bounds); 102 return new OpenLayers.Tile.Image(this, position, bounds, url, this.tileSize); 103 }, 104 105 CLASS_NAME: "OpenLayers.Layer.TDT" 106 });
天地图底图和标注,分为两个图层来加载显示的。
1 //天地图 2 map.addLayers([ 3 new OpenLayers.Layer.XYZ( 4 "天地图", 5 [ 6 "http://t0.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 7 "http://t1.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 8 "http://t2.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 9 "http://t3.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 10 "http://t4.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 11 "http://t5.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 12 "http://t6.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}", 13 "http://t7.tianditu.com/DataServer?T=vec_w&X=${x}&Y=${y}&L=${z}" 14 ], 15 { 16 projection: new OpenLayers.Projection("EPSG:900913"), 17 isBaseLayer: true 18 } 19 ), 20 new OpenLayers.Layer.XYZ( 21 "天地图标注", 22 [ 23 "http://t0.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 24 "http://t1.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 25 "http://t2.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 26 "http://t3.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 27 "http://t4.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 28 "http://t5.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 29 "http://t6.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}", 30 "http://t7.tianditu.com/DataServer?T=cva_w&X=${x}&Y=${y}&L=${z}" 31 ], 32 { 33 projection: new OpenLayers.Projection("EPSG:900913"), 34 isBaseLayer: false, 35 visibility:false 36 37 } 38 ) 39 ] 40 );
火星坐标和WGS84坐标相互转换的js文件,百度搜一下有下载的文件:
1 var GPS = { 2 PI: 3.14159265358979324, 3 x_pi: 3.14159265358979324 * 3000.0 / 180.0, 4 delta: function (lat, lon) { 5 // Krasovsky 1940 6 // 7 // a = 6378245.0, 1/f = 298.3 8 // b = a * (1 - f) 9 // ee = (a^2 - b^2) / a^2; 10 var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。 11 var ee = 0.00669342162296594323; // ee: 椭球的偏心率。 12 var dLat = this.transformLat(lon - 105.0, lat - 35.0); 13 var dLon = this.transformLon(lon - 105.0, lat - 35.0); 14 var radLat = lat / 180.0 * this.PI; 15 var magic = Math.sin(radLat); 16 magic = 1 - ee * magic * magic; 17 var sqrtMagic = Math.sqrt(magic); 18 dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI); 19 dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI); 20 return { 'lat': dLat, 'lon': dLon }; 21 }, 22 23 //WGS-84 to GCJ-02 24 gcj_encrypt: function (wgsLat, wgsLon) { 25 if (this.outOfChina(wgsLat, wgsLon)) 26 return { 'lat': wgsLat, 'lon': wgsLon }; 27 28 var d = this.delta(wgsLat, wgsLon); 29 return { 'lat': wgsLat + d.lat, 'lon': wgsLon + d.lon }; 30 }, 31 //GCJ-02 to WGS-84 32 gcj_decrypt: function (gcjLat, gcjLon) { 33 if (this.outOfChina(gcjLat, gcjLon)) 34 return { 'lat': gcjLat, 'lon': gcjLon }; 35 36 var d = this.delta(gcjLat, gcjLon); 37 return { 'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon }; 38 }, 39 //GCJ-02 to WGS-84 exactly 40 gcj_decrypt_exact: function (gcjLat, gcjLon) { 41 var initDelta = 0.01; 42 var threshold = 0.000000001; 43 var dLat = initDelta, dLon = initDelta; 44 var mLat = gcjLat - dLat, mLon = gcjLon - dLon; 45 var pLat = gcjLat + dLat, pLon = gcjLon + dLon; 46 var wgsLat, wgsLon, i = 0; 47 while (1) { 48 wgsLat = (mLat + pLat) / 2; 49 wgsLon = (mLon + pLon) / 2; 50 var tmp = this.gcj_encrypt(wgsLat, wgsLon) 51 dLat = tmp.lat - gcjLat; 52 dLon = tmp.lon - gcjLon; 53 if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold)) 54 break; 55 56 if (dLat > 0) pLat = wgsLat; else mLat = wgsLat; 57 if (dLon > 0) pLon = wgsLon; else mLon = wgsLon; 58 59 if (++i > 10000) break; 60 } 61 //console.log(i); 62 return { 'lat': wgsLat, 'lon': wgsLon }; 63 }, 64 //GCJ-02 to BD-09 65 bd_encrypt: function (gcjLat, gcjLon) { 66 var x = gcjLon, y = gcjLat; 67 var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi); 68 var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi); 69 bdLon = z * Math.cos(theta) + 0.0065; 70 bdLat = z * Math.sin(theta) + 0.006; 71 return { 'lat': bdLat, 'lon': bdLon }; 72 }, 73 //BD-09 to GCJ-02 74 bd_decrypt: function (bdLat, bdLon) { 75 var x = bdLon - 0.0065, y = bdLat - 0.006; 76 var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi); 77 var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi); 78 var gcjLon = z * Math.cos(theta); 79 var gcjLat = z * Math.sin(theta); 80 return { 'lat': gcjLat, 'lon': gcjLon }; 81 }, 82 //WGS-84 to Web mercator 83 //mercatorLat -> y mercatorLon -> x 84 mercator_encrypt: function (wgsLat, wgsLon) { 85 var x = wgsLon * 20037508.34 / 180.; 86 var y = Math.log(Math.tan((90. + wgsLat) * this.PI / 360.)) / (this.PI / 180.); 87 y = y * 20037508.34 / 180.; 88 return { 'lat': y, 'lon': x }; 89 /* 90 if ((Math.abs(wgsLon) > 180 || Math.abs(wgsLat) > 90)) 91 return null; 92 var x = 6378137.0 * wgsLon * 0.017453292519943295; 93 var a = wgsLat * 0.017453292519943295; 94 var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a))); 95 return {'lat' : y, 'lon' : x}; 96 //*/ 97 }, 98 // Web mercator to WGS-84 99 // mercatorLat -> y mercatorLon -> x 100 mercator_decrypt: function (mercatorLat, mercatorLon) { 101 var x = mercatorLon / 20037508.34 * 180.; 102 var y = mercatorLat / 20037508.34 * 180.; 103 y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180.)) - this.PI / 2); 104 return { 'lat': y, 'lon': x }; 105 /* 106 if (Math.abs(mercatorLon) < 180 && Math.abs(mercatorLat) < 90) 107 return null; 108 if ((Math.abs(mercatorLon) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892)) 109 return null; 110 var a = mercatorLon / 6378137.0 * 57.295779513082323; 111 var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0); 112 var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323; 113 return {'lat' : y, 'lon' : x}; 114 //*/ 115 }, 116 // two point's distance 117 distance: function (latA, lonA, latB, lonB) { 118 var earthR = 6371000.; 119 var x = Math.cos(latA * this.PI / 180.) * Math.cos(latB * this.PI / 180.) * Math.cos((lonA - lonB) * this.PI / 180); 120 var y = Math.sin(latA * this.PI / 180.) * Math.sin(latB * this.PI / 180.); 121 var s = x + y; 122 if (s > 1) s = 1; 123 if (s < -1) s = -1; 124 var alpha = Math.acos(s); 125 var distance = alpha * earthR; 126 return distance; 127 }, 128 outOfChina: function (lat, lon) { 129 if (lon < 72.004 || lon > 137.8347) 130 return true; 131 if (lat < 0.8293 || lat > 55.8271) 132 return true; 133 return false; 134 }, 135 transformLat: function (x, y) { 136 var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); 137 ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0; 138 ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0; 139 ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0; 140 return ret; 141 }, 142 transformLon: function (x, y) { 143 var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); 144 ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0; 145 ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0; 146 ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0; 147 return ret; 148 } 149 };