phpIPAM 使用leaflet.js切换百度瓦片地图

2023-08-16  本文已影响0人  风吹小树摇

phpIPAM使用leaflet.js加载并渲染地图,默认使用openstreetmap瓦片地图,由于众所周知的原因在国内无法加载openstreetmap底图。
经度娘了解尝试将openstreetmap地图切换为百度瓦片地图,过程如下:

一、准备

下载leaflet.ChineseTmsProviders.js到目录phpipam/js

cd /opt/phpiamp/js
wget https://jsdelivr.b-cdn.net/gh/htoooth/Leaflet.ChineseTmsProviders@master/src/leaflet.ChineseTmsProviders.js

二、使用百度API获取坐标

第一步

修改nominatim表的url字段,将openstreetmap API更换为百度地图API

http://api.map.baidu.com/geocoding/v3/?output=json&ak='Your baidu api key!'&address=
image.png

第二步

修改 phpipam/functions/classes/class.OpenStreetMap.php -> get_latlng_from_address()函数

    /**
     * Perform Geocoding lookup
     *
     * @param   string  $address
     * @return  array
     */
    public function get_latlng_from_address($address) {
        $results = ['lat' => null, 'lng' => null, 'error' => null];
        if (!is_string($address) || is_blank($address)) {
            $results['error'] = _('invalid address');
            return $results;
        }
        if (Config::ValueOf('offline_mode')) {
            $result['error'] = _('Internet access disabled in config.php');
            return $result;
        }
        try {
            // Obtain exclusive MySQL row lock
            $Lock = new LockForUpdate($this->Database, 'nominatim', 1);
            $elapsed = -microtime(true);
            // Check cached results from the last 24h
            $cached_result = $this->search_geo_cache($address, true);
            if ($cached_result) {
                $json = pf_json_decode($cached_result->lat_lng, true);
                if (is_array($json)) {
                    return $json;
                }
            }
            $url = $Lock->locked_row->url;
            //$url = $url . "?format=json&q=" . rawurlencode($address);
            //直接读取nominatim.url
            $url = $url . rawurlencode($address);

            $headers = [
                'User-Agent: phpIPAM/' . VERSION_VISIBLE . ' (Open source IP address management)',
                'Referer: ' . $this->createURL() . create_link()
            ];
            // fetch geocoding data with proxy settings from config.php
            $lookup = $this->curl_fetch_url($url, $headers);
            if ($lookup['result_code'] != 200) {
                // Lookup failed - Check cache again with no time limit.
                $cached_result = $this->search_geo_cache($address, false);
                if ($cached_result) {
                    $json = pf_json_decode($cached_result->lat_lng, true);
                    if (is_array($json)) {
                        return $json;
                    }
                }
                throw new \Exception($lookup['error_msg']);
            }
            $geo = pf_json_decode($lookup['result'], true);
            if (!is_array($geo)) {
                throw new \Exception(_('Invalid json response from nominatim'));
            }
//            if (isset($geo['0']['lat']) && isset($geo['0']['lon'])) {
//                $results['lat'] = $geo['0']['lat'];
//                $results['lng'] = $geo['0']['lon'];
//            }
//百度地图API格式数据
            if (isset($geo['result']['location']['lat']) && isset($geo['result']['location']['lng'])) {
                $results['lat'] = $geo['result']['location']['lat'];
                $results['lng'] = $geo['result']['location']['lng'];
            }

            $this->update_geo_cache($address, json_encode($results));
        } catch (\Exception $e) {
            $results = ['lat' => null, 'lng' => null, 'error' => $e->getMessage()];
        }
        // Ensure we hold the exclusive database lock for a minimum of 1 second
        // (< 1 requests/s across all load-balanced instances of this app)
        $elapsed += microtime(true);
        if ($elapsed < 0) {
            time_nanosleep(0, 1000000000);
        } elseif ($elapsed < 1) {
            time_nanosleep(0, 1000000000 * (1 - $elapsed));
        }
        return $results;
    }

三、调用百度瓦片地图

第一步

修改phpipam/index.php,找到<script src="js/leaflet.fullscreen.min.js"></script>,在下面插入

                <!--引入proj4,百度地图用--> 
                <script src="https://cdn.bootcss.com/proj4js/2.4.3/proj4.js"></script>
                <script src="https://cdn.bootcss.com/proj4leaflet/1.0.1/proj4leaflet.min.js"></script>

                <!-- 引入互联网地图插件 -->
                <script src="js/leaflet.ChineseTmsProviders.js"></script>

第二步

修改 phpipam/functions/classes/class.OpenStreetMap.php -> map()函数

    /**
     * Output OpenStreetMap HTML/JS
     *
     * @param   null|int  $height
     * @return  void
     */
    public function map($height = null)
    {
        if (sizeof($this->geodata) == 0) {
            $this->Result->show("info", _("No Locations with coordinates configured"), false);
            return;
        }

?>
        <div style="width:100%; height:<?php print isset($height) ? $height : "600px" ?>;" id="map_overlay">
            <!--百度地图 div-->
            <div id="map" style="width:100%; height:100%;"></div>
        </div>
        <script>
            function osm_style(feature) {
                return feature.properties && feature.properties.style;
            }

            function osm_onEachFeature(feature, layer) {
                if (feature.properties && feature.properties.popupContent) {
                    layer.bindPopup(feature.properties.popupContent);
                }
            }

            function osm_point_to_circle(feature, latlng) {
                return L.circleMarker(latlng, {
                    radius: 8,
                    fillColor: "#ff7800",
                    color: "#000",
                    weight: 1,
                    opacity: 1,
                    fillOpacity: 0.8
                });
            }

            var geodata = <?php print json_encode($this->geodata); ?>;
            var polydata = <?php print json_encode($this->polydata); ?>;

//            var mapOptions = {
//                preferCanvas: true,
//                attributionControl: true,
//                zoom: -1,
//                fullscreenControl: true,
//            }
            var mapOptions = { 
                crs: L.CRS.Baidu, 
                fullscreenControl: true,
                zoom: 17,
                layers:[]
            }
            var geoJSONOptions = { 
                  style: osm_style, 
                  onEachFeature: osm_onEachFeature, 
                  pointToLayer: osm_point_to_circle,
            }

//            var layerOptions = {
//                attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
//            }

            // Creating a map object
//            var map = new L.map('osmap', mapOptions);
             var map = L.map('map',mapOptions);
           // Add circuit lines
            for (var key in polydata) {
                var fmt = key.split('::::');
                if (fmt[1] == "Solid") {
                    L.polyline(polydata[key], {
                        'color': fmt[0]
                    }).addTo(map);
                } else {
                    L.polyline(polydata[key], {
                        'color': fmt[0],
                        dashArray: '20, 10'
                    }).addTo(map);
                }
            };
            // Add location markers
            geoJSON = L.geoJSON(geodata, geoJSONOptions).addTo(map);
            map.fitBounds(geoJSON.getBounds());

            // Add Tile layer
//            var layer = new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', layerOptions);
            var layer = L.tileLayer.chinaProvider('Baidu.Normal.Map').addTo(map);
            map.addLayer(layer);
        </script>
<?php
    }

参考:
gisarmory/Leaflet.InternetMapCorrection: 互联网地图纠偏 (github.com)

上一篇 下一篇

猜你喜欢

热点阅读