地圖區域是一個市,偏移量能夠近似認爲是固定不變的,經過修改Leaflet-src.js源碼中的_update方法和_addTile方法對瓦片進行偏移糾偏。html
Leaflet版本v1.3.4,要修改的_update和_addTile方法和最新版本1.6.0區別不大。app
一、在_update方法中添加以下代碼,瓦片圖偏移後,在邊緣位置須要補充瓦片圖顯示,否則邊緣會出現空白:async
//處理糾偏後瓦片顯示 var ratio = 1 / Math.pow(2, (18 - this._tileZoom)); //計算糾偏比率 var deltaX = 0; var deltaY = 0; if (this._map.options.offsetX) deltaX = this._map.options.offsetX * ratio / 256; if (this._map.options.offsetY) deltaY = this._map.options.offsetY * ratio / 256; if (deltaX > 0) tileRange.max.x += (Math.round(deltaX) + 1); if (deltaY > 0) tileRange.max.y += (Math.round(deltaY) + 1); if (deltaX < 0) tileRange.min.x -= (Math.floor(deltaX) - 1); if (deltaY < 0) tileRange.min.y -= (Math.floor(deltaY) - 1);
二、在_update方法中修改以下代碼:ide
for (i = 0; i < queue.length; i++) { this._addTile(queue[i], fragment, ratio); }
三、在_addTile方法中添加以下代碼,從新計算瓦片的像素位置:工具
//糾偏 if (this._map.options.offsetX) tilePos.x -= Math.floor(this._map.options.offsetX * ratio); if (this._map.options.offsetY) tilePos.y -= Math.floor(this._map.options.offsetY * ratio);
_update方法完整代碼:this
// Private method to load tiles in the grid's active zoom level according to map bounds _update: function (center) { var map = this._map; if (!map) { return; } var zoom = this._clampZoom(map.getZoom()); if (center === undefined) { center = map.getCenter(); } if (this._tileZoom === undefined) { return; } // if out of minzoom/maxzoom var pixelBounds = this._getTiledPixelBounds(center), tileRange = this._pxBoundsToTileRange(pixelBounds), tileCenter = tileRange.getCenter(), queue = [], margin = this.options.keepBuffer, noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]), tileRange.getTopRight().add([margin, -margin])); // Sanity check: panic if the tile range contains Infinity somewhere. if (!(isFinite(tileRange.min.x) && isFinite(tileRange.min.y) && isFinite(tileRange.max.x) && isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); } for (var key in this._tiles) { var c = this._tiles[key].coords; if (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) { this._tiles[key].current = false; } } // _update just loads more tiles. If the tile zoom level differs too much // from the map's, let _setView reset levels and prune old tiles. if (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; } //處理糾偏後瓦片顯示 var ratio = 1 / Math.pow(2, (18 - this._tileZoom)); //計算糾偏比率 var deltaX = 0; var deltaY = 0; if (this._map.options.offsetX) deltaX = this._map.options.offsetX * ratio / 256; if (this._map.options.offsetY) deltaY = this._map.options.offsetY * ratio / 256; if (deltaX > 0) tileRange.max.x += (Math.round(deltaX) + 1); if (deltaY > 0) tileRange.max.y += (Math.round(deltaY) + 1); if (deltaX < 0) tileRange.min.x -= (Math.floor(deltaX) - 1); if (deltaY < 0) tileRange.min.y -= (Math.floor(deltaY) - 1); // create a queue of coordinates to load tiles from for (var j = tileRange.min.y; j <= tileRange.max.y; j++) { for (var i = tileRange.min.x; i <= tileRange.max.x; i++) { var coords = new Point(i, j); coords.z = this._tileZoom; if (!this._isValidTile(coords)) { continue; } var tile = this._tiles[this._tileCoordsToKey(coords)]; if (tile) { tile.current = true; } else { queue.push(coords); } } } // sort tile queue to load tiles in order of their distance to center queue.sort(function (a, b) { return a.distanceTo(tileCenter) - b.distanceTo(tileCenter); }); if (queue.length !== 0) { // if it's the first batch of tiles to load if (!this._loading) { this._loading = true; // @event loading: Event // Fired when the grid layer starts loading tiles. this.fire('loading'); } // create DOM fragment to append tiles in one batch var fragment = document.createDocumentFragment(); for (i = 0; i < queue.length; i++) { this._addTile(queue[i], fragment, ratio); } this._level.el.appendChild(fragment); } },
_addTile方法完整代碼:spa
_addTile: function (coords, container, ratio) { var tilePos = this._getTilePos(coords), key = this._tileCoordsToKey(coords); var tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords)); this._initTile(tile); // if createTile is defined with a second argument ("done" callback), // we know that tile is async and will be ready later; otherwise if (this.createTile.length < 2) { // mark tile as ready, but delay one frame for opacity animation to happen requestAnimFrame(bind(this._tileReady, this, coords, null, tile)); } //糾偏 if (this._map.options.offsetX) tilePos.x -= Math.floor(this._map.options.offsetX * ratio); if (this._map.options.offsetY) tilePos.y -= Math.floor(this._map.options.offsetY * ratio); setPosition(tile, tilePos); // save tile in cache this._tiles[key] = { el: tile, coords: coords, current: true }; container.appendChild(tile); // @event tileloadstart: TileEvent // Fired when a tile is requested and starts loading. this.fire('tileloadstart', { tile: tile, coords: coords }); },
如何使用:code
一、JS引用由leaflet.js修改成引用leaflet-src.jshtm
二、建立地圖見以下代碼,注意offsetX和offsetY參數,不一樣的城市,參數值不一樣,參數值能夠用太樂地圖下載器軟件中的糾偏工具計算:blog
var map = new L.Map('map', { center: centerLatLng, zoom: 12, minZoom: 8, maxZoom: 18, maxBounds: mapBounds, offsetX: 1020, offsetY: 517, layers: [tileLayer], attributionControl: false, doubleClickZoom: false, zoomControl: false });
還有另外一種糾偏方法,能夠經過處理瓦片圖進行糾偏:http://www.javashuo.com/article/p-bjsehhnd-er.html