zoukankan      html  css  js  c++  java
  • Leaflet 百度、高德地图瓦片坐标 偏移 纠偏

    实现地图瓦片纠偏的leaflet.mapCorrection.js代码:

    //坐标转换
    L.CoordConvertor = function () {
    
        /**百度转84*/
        this.bd09_To_gps84 = function (lng, lat) {
            var gcj02 = this.bd09_To_gcj02(lng, lat);
            var map84 = this.gcj02_To_gps84(gcj02.lng, gcj02.lat);
            return map84;
        }
    
        /**84转百度*/
        this.gps84_To_bd09 = function (lng, lat) {
            var gcj02 = this.gps84_To_gcj02(lng, lat);
            var bd09 = this.gcj02_To_bd09(gcj02.lng, gcj02.lat);
            return bd09;
        }
    
        /**84转火星*/
        this.gps84_To_gcj02 = function (lng, lat) {
            var dLat = transformLat(lng - 105.0, lat - 35.0);
            var dLng = transformLng(lng - 105.0, lat - 35.0);
            var radLat = lat / 180.0 * pi;
            var magic = Math.sin(radLat);
            magic = 1 - ee * magic * magic;
            var sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
            var mgLat = lat + dLat;
            var mgLng = lng + dLng;
            var newCoord = {
                lng: mgLng,
                lat: mgLat
            };
            return newCoord;
        }
    
        /**火星转84*/
        this.gcj02_To_gps84 = function (lng, lat) {
            var coord = transform(lng, lat);
            var lontitude = lng * 2 - coord.lng;
            var latitude = lat * 2 - coord.lat;
            var newCoord = {
                lng: lontitude,
                lat: latitude
            };
            return newCoord;
        }
    
        /**火星转百度*/
        this.gcj02_To_bd09 = function (x, y) {
            var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
            var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
            var bd_lng = z * Math.cos(theta) + 0.0065;
            var bd_lat = z * Math.sin(theta) + 0.006;
            var newCoord = {
                lng: bd_lng,
                lat: bd_lat
            };
            return newCoord;
        }
    
        /**百度转火星*/
        this.bd09_To_gcj02 = function (bd_lng, bd_lat) {
            var x = bd_lng - 0.0065;
            var y = bd_lat - 0.006;
            var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
            var gg_lng = z * Math.cos(theta);
            var gg_lat = z * Math.sin(theta);
            var newCoord = {
                lng: gg_lng,
                lat: gg_lat
            };
            return newCoord;
        }
    
        var pi = 3.1415926535897932384626;
        var a = 6378245.0;
        var ee = 0.00669342162296594323;
        var x_pi = pi * 3000.0 / 180.0;
        var R = 6378137;
    
        function transform(lng, lat) {
            var dLat = transformLat(lng - 105.0, lat - 35.0);
            var dLng = transformLng(lng - 105.0, lat - 35.0);
            var radLat = lat / 180.0 * pi;
            var magic = Math.sin(radLat);
            magic = 1 - ee * magic * magic;
            var sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
            var mgLat = lat + dLat;
            var mgLng = lng + dLng;
            var newCoord = {
                lng: mgLng,
                lat: mgLat
            };
            return newCoord;
        }
    
        function transformLat(x, y) {
            var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }
    
        function transformLng(x, y) {
            var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
            return ret;
        }
    }
    
    L.coordConvertor = function () {
        return new L.CoordConvertor()
    }
    
    L.tileLayer.chinaProvider = function (type, options) {
        options = options || {}
        options.coordType = getCoordType(type);
        return new L.TileLayer.ChinaProvider(type, options);
    
        //获取坐标类型
        function getCoordType(type) {
            var parts = type.split('.');
            var providerName = parts[0];
            var zbName = "wgs84"
            switch (providerName) {
                case "Geoq":
                case "GaoDe":
                case "Google":
                    zbName = "gcj02";
                    break;
                case "Baidu":
                    zbName = "bd09";
                    break;
                case "OSM":
                case "TianDiTu":
                    zbName = "wgs84";
                    break;
            }
            return zbName;
        }
    };
    
    L.GridLayer.include({
        _setZoomTransform: function (level, _center, zoom) {
            var center = _center;
            if (center != undefined && this.options) {
                if (this.options.coordType == 'gcj02') {
                    center = L.coordConvertor().gps84_To_gcj02(_center.lng, _center.lat);
                } else if (this.options.coordType == 'bd09') {
                    center = L.coordConvertor().gps84_To_bd09(_center.lng, _center.lat);
                }
            }
            var scale = this._map.getZoomScale(zoom, level.zoom),
                translate = level.origin.multiplyBy(scale)
                    .subtract(this._map._getNewPixelOrigin(center, zoom)).round();
    
            if (L.Browser.any3d) {
                L.DomUtil.setTransform(level.el, translate, scale);
            } else {
                L.DomUtil.setPosition(level.el, translate);
            }
        },
        _getTiledPixelBounds: function (_center) {
            var center = _center;
            if (center != undefined && this.options) {
                if (this.options.coordType == 'gcj02') {
                    center = L.coordConvertor().gps84_To_gcj02(_center.lng, _center.lat);
                } else if (this.options.coordType == 'bd09') {
                    center = L.coordConvertor().gps84_To_bd09(_center.lng, _center.lat);
                }
            }
            var map = this._map,
                mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
                scale = map.getZoomScale(mapZoom, this._tileZoom),
                pixelCenter = map.project(center, this._tileZoom).floor(),
                halfSize = map.getSize().divideBy(scale * 2);
    
            return new L.Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
        }
    });
    View Code

    Demo主要代码: 

    index.html代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Leaflet</title>
    
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <link rel="stylesheet" href="libs/leaflet/leaflet.css">
        <link rel="stylesheet" href="css/index.css">
    
        <script type="text/javascript" src="libs/jquery-1.9.1.js"></script>
        <script type="text/javascript" src="libs/leaflet/leaflet-src.js"></script>
        <script type="text/javascript" src="libs/leaflet-plugins/proj4-compressed.js"></script>
        <script type="text/javascript" src="libs/leaflet-plugins/proj4leaflet.js"></script>
        <script type="text/javascript" src="libs/leaflet-plugins/leaflet.baidu.js"></script>
        <script type="text/javascript" src="libs/leaflet-plugins/leaflet.ChineseTmsProviders.js"></script>
        <script type="text/javascript" src="libs/leaflet-plugins/leaflet.mapCorrection.js"></script>
    </head>
    
    <body>
        <div id="map" style="cursor:default;"></div>
        <div id="mouseposition"></div>
        <div id="mapzoom"></div>
        <!-- 用于显示调试信息 -->
        <div
            style="display:none; position:absolute; right:0; bottom:30px; background-color:transparent; 1000px; height:30px; margin-right:3px; z-index:99999; border:solid 1px transparent;">
            <input type="text" id="msg" value=""
                style="990px; font-size:12px; padding-left:3px; padding-right:3px; " />
        </div>
        <div
            style="display:none; position:absolute; left:20px; top:20px; background-color:transparent; 1200px; height:30px; z-index:99998; border:solid 1px transparent;">
            <input type="button" onclick="alert('1')" value="测试按钮" />
        </div>
        <script type="text/javascript" src="config/config.js"></script>
        <script type="module" src="js/index.js"></script>
    </body>
    
    </html>
    View Code

    index.js代码:

    import { Map } from './map.js'
    import { Marker } from './marker.js'
    
    let map = new Map(tileUrl, {
        centerLatLng: L.latLng(31.81880456, 117.18087366),
        mapBounds: L.latLngBounds(L.latLng(31.0, 116.6), L.latLng(32.6, 117.8))
    });
    
    let marker = new Marker(117.18087366, 31.81880456, {
        id: 1,
        name: '测试marker'
    });
    
    map.deviceLayer.addLayer(marker.marker);
    View Code

    map.js代码:

    代码中 new L.TileLayer 时,添加属性 coordType: 'gcj02' ,即可实现高德地图瓦片偏移的纠偏

    如果是百度地图瓦片,则添加属性 coordType: 'bd09' 即可

    /**
     * 地图
     */
    class Map {
    
        map
        deviceLayer = L.layerGroup()
    
        options = {
            // L.latLng
            centerLatLng: undefined,
    
            // L.latLngBounds
            mapBounds: undefined
        }
    
        constructor(tileUrl, options) {
    
            Object.assign(this.options, options);
    
            let tileLayer = new L.TileLayer(tileUrl, {
                minZoom: 8,
                maxZoom: 18,
                coordType: 'gcj02'
            });
    
            this.map = new L.Map('map', {
                center: this.options.centerLatLng,
                zoom: 12,
                minZoom: 8,
                maxZoom: 18,
                maxBounds: this.options.mapBounds,
                layers: [tileLayer],
                attributionControl: false,
                doubleClickZoom: false,
                zoomControl: false
            });
    
            this.map.addLayer(this.deviceLayer); //设备图层
    
            L.control.scale().addTo(this.map); //比例尺
    
            //显示经纬度和地图层级
            let this_ = this;
            this.map.addEventListener("mousemove", function (e) {
                this_.showMousePosition(e);
                this_.showMapZoom();
            });
            this.map.addEventListener("zoomend", function (e) {
                this_.showMapZoom();
            });
        }
    
        showMousePosition(e) {
            if (!this.mousePositionDiv) {
                this.mousePositionDiv = $('#mouseposition');
            }
            this.mousePositionDiv.text(e.latlng.lng.toFixed(8) + ", " + e.latlng.lat.toFixed(8));
        }
    
        showMapZoom() {
            if (!this.mapZoomDiv) {
                this.mapZoomDiv = $('#mapzoom');
            }
            this.mapZoomDiv.text(this.map.getZoom().toString());
        }
    }
    
    export { Map }
    View Code

    完整Demo代码下载:

    地图瓦片纠偏Demo.zip

    代码实现的功能:百度、高德离线地图瓦片加载和纠偏

    代码使用了ES6模块化开发,必须部署在服务器上才能在浏览器中访问,可以使用IIS或Tomcat部署

    效果图:

    高德地图:

     

    百度地图:

    参考github:

    https://github.com/gisarmory/Leaflet.InternetMapCorrection

  • 相关阅读:
    一维,二维差分 (P3397 地毯)
    P3406 海底高铁
    P2004 领地选择
    priority_queue 大顶堆与小顶堆的用法 & 常见数据结构时间复杂度
    AcWing 电影
    P2678 跳石头
    HDU2041超级楼梯
    HDU2087剪花布条
    n条线分平面问题解决方法总结
    HDU2034 人见人爱A-B(C++)
  • 原文地址:https://www.cnblogs.com/s0611163/p/15606460.html
Copyright © 2011-2022 走看看