Leaflet 地圖偏移 地圖糾偏

    地圖區域是一個市,偏移量能夠近似認爲是固定不變的,經過修改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);
View Code

二、在_update方法中修改以下代碼:ide

            for (i = 0; i < queue.length; i++) {
                this._addTile(queue[i], fragment, ratio);
            }
View Code

三、在_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);
View Code

 

_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);
        }
    },
View Code

_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
        });
    },
View Code

 

如何使用: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 });
View Code

 

還有另外一種糾偏方法,能夠經過處理瓦片圖進行糾偏:http://www.javashuo.com/article/p-bjsehhnd-er.html

相關文章
相關標籤/搜索