zoukankan      html  css  js  c++  java
  • Leaflet 地图偏移 地图纠偏

        地图区域是一个市,偏移量可以近似认为是固定不变的,通过修改Leaflet-src.js源码中的_update方法和_addTile方法对瓦片进行偏移纠偏。

        Leaflet版本v1.3.4,要修改的_update和_addTile方法和最新版本1.6.0区别不大。

    1、在_update方法中添加如下代码,瓦片图偏移后,在边缘位置需要补充瓦片图显示,不然边缘会出现空白:

            //处理纠偏后瓦片显示
            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

    2、在_update方法中修改如下代码:

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

    3、在_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方法完整代码:

        // 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方法完整代码:

        _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

    如何使用:

    1、JS引用由leaflet.js修改为引用leaflet-src.js

    2、创建地图见如下代码,注意offsetX和offsetY参数,不同的城市,参数值不同,参数值可以用太乐地图下载器软件中的纠偏工具计算:

    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

    还有另一种纠偏方法,可以通过处理瓦片图进行纠偏:https://www.cnblogs.com/s0611163/p/12034779.html

  • 相关阅读:
    高级(线性)素数筛
    Dijkstra(迪杰斯特拉)算法
    简单素数筛
    【解题报告】 POJ1958 奇怪的汉诺塔(Strange Tower of Hanoi)
    4 jQuery Chatting Plugins | jQuery UI Chatbox Plugin Examples Like Facebook, Gmail
    Web User Control Collection data is not storing
    How to turn on IE9 Compatibility View programmatically in Javascript
    从Javascrip 脚本中执行.exe 文件
    HtmlEditorExtender Ajax
    GRIDVIEW模板中查找控件的方式JAVASCRIPT
  • 原文地址:https://www.cnblogs.com/s0611163/p/13396622.html
Copyright © 2011-2022 走看看