地图组件Leaflet地图偏移问题

转自:http://blog.csdn.net/liufeng0209/article/details/41896935

Leaflet的好处就不多说了,简单的几点:轻量、支持HTML5、插件多,在与图形组件(如HT组件)结合后,可以开发出丰富的GIS应用,可以说几乎所有的GIS场景都能支持。

在使用GIS的时候,想必有个问题一直困扰开发者,就是我们的底图基本上都是有偏移的,如果使用GPS采集的资源(真实经纬度)叠加到底图上,与底图有很大的偏移,叠加不上。从测试上来说,高德的底图,偏差可达到20公里。

处理偏移问题,一般有两个思路:

第一个是将真实的经纬度按照偏移算法(一般底图供应商会提供)偏移到加密的地图上,从而达到叠加效果。这样的问题是相当于将错就错,如果从地图上去采集经纬度就是偏移的,最后还得纠偏回去。而纠偏又是一个大问题,几乎所有的底图供应商都不提供纠偏算法,单单这个问题,都可以再写一篇文章。

第二个是改造地图组件,将底图进行反向偏移,这样GPS采集的经纬度可以无缝的叠加上,在地图上采集的经纬度都是无需纠偏的。进行底图偏移的前提是,需要知道偏移量offset,如果是线性偏移,这个offset就是个常量,如果不是线性偏移,则这个offset是依赖于视窗中心点的变量。

笔者查看Leaflet的源码,其中并没有对偏移的处理方法,在阅读源码并经过反复测试后,获得了以下的思路:

1.在获取切片的时候,计算切片X,Y值的时候增加上偏移量;

_update: function () {

					 //hqj增加偏移支持 start
					if (!this._map) { return; }
					var map = this._map,
                        bounds = map.getPixelBounds(),
                        zoom = map.getZoom(),
                        tileSize = this._getTileSize(),
					sw = map.unproject(bounds.getBottomLeft()),//获取左下角经纬度
					ne = map.unproject(bounds.getTopRight());//获取右上角经纬度
					if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {  
						return;  
					}     
					var offsetX = this.options.offsetX;//经度偏移量  
					var offsetY = this.options.offsetY;//纬度偏移量  
					if(offsetX != null  && offsetY != null)  
					{  
						sw = new L.LatLng(sw.lat - parseFloat(offsetY),sw.lng - parseFloat(offsetX));//增加偏移量  
						ne = new L.LatLng(ne.lat - parseFloat(offsetY),ne.lng - parseFloat(offsetX));  
						  
						var swPoint = map.project(sw);//将经纬度进行投影 
						var nePoint = map.project(ne);  
						  
						bounds = L.bounds(swPoint,nePoint);  
					}  
					var tileBounds = L.bounds(
                            bounds.min.divideBy(tileSize)._floor(),
                            bounds.max.divideBy(tileSize)._floor());

                    this._addTilesFromCenterOut(tileBounds);

                    if (this.options.unloadInvisibleTiles || this.options.reuseTiles) {
                        this._removeOtherTiles(tileBounds);
                    }
					//hqj增加偏移支持 end
					
                    /*if (!this._map) { return; }

                    var map = this._map,
                        bounds = map.getPixelBounds(),
                        zoom = map.getZoom(),
                        tileSize = this._getTileSize();

                    if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
                        return;
                    }					

                    var tileBounds = L.bounds(
                            bounds.min.divideBy(tileSize)._floor(),
                            bounds.max.divideBy(tileSize)._floor());

                    this._addTilesFromCenterOut(tileBounds);

                    if (this.options.unloadInvisibleTiles || this.options.reuseTiles) {
                        this._removeOtherTiles(tileBounds);
                    }*/
                },

2.在显示图片的时候,图片位置减去偏移量;

_addTile: function (tilePoint, container) {
                    var tilePos = this._getTilePos(tilePoint);
					//hqj增加偏移支持 start
					var offsetX = this.options.offsetX;  
					var offsetY = this.options.offsetY;  
					  
					if(offsetX != null  && offsetY != null)  
					{  
						var latLng = this._map.layerPointToLatLng(tilePos);  
						tilePos = this._map.latLngToLayerPoint(new L.LatLng(latLng.lat + parseFloat(offsetY),latLng.lng + parseFloat(offsetX)));  
					}  
					//hqj增加偏移支持 end
                    // get unused tile - or create a new tile
                    var tile = this._getTile();
                    /*
                     Chrome 20 layouts much faster with top/left (verify with timeline, frames)
                     Android 4 browser has display issues with top/left and requires transform instead
                     (other browsers don't currently care) - see debug/hacks/jitter.html for an example
                     */
                    L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome);

                    this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;

                    this._loadTile(tile, tilePoint);

                    if (tile.parentNode !== this._tileContainer) {
                        container.appendChild(tile);
                    }
                },

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值