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

  • 相关阅读:
    Qt之等待提示框(QTimer)
    Qt之等待提示框(QPropertyAnimation)
    FormatUtil类型格式转换
    FirstLetterUtil
    文件上传下载
    file相关的操作,(md5,word转html,复制,删除等)
    SessionListener失败,退出
    JackJson的一些方法
    全局常量
    session用户账号认证(一个用户登陆,踢出前一个用户)
  • 原文地址:https://www.cnblogs.com/s0611163/p/13396622.html
Copyright © 2011-2022 走看看