Google Maps API and KML File LocalHost Development Options

前端 未结 2 1405
别跟我提以往
别跟我提以往 2020-12-04 18:38

The Google Maps JavaScript version 3 API library documentation clearly explains:

The Google Maps API supports the KML and GeoRSS data formats for di

相关标签:
2条回答
  • 2020-12-04 19:12

    It seems like you've outlined the options pretty well:

    If you want to work with local data, without involving a publicly accessible webserver, you'll need to use a javascript-based approach to parse the KML and load it onto the map. While this won't perfectly replicate the Google functionality, it is likely good enough for initial development if you only care about displaying the KML features. In this case, I'd probably set up a stub class, like this:

        // I'll assume you have a global namespace called MyProject
        MyProject.LOCAL_KML = true;
    
        MyProject.KmlLayer = function(url) {
            // parse the KML, maybe caching an array of markers or polygons,
            // using one of the libraries you list in your question
        };
    
        // now stub out the methods you care about, based on
        // http://code.google.com/apis/maps/documentation/javascript/reference.html#KmlLayer
        MyProject.KmlLayer.prototype.setMap = function(map) {
            // add the markers and polygons to the map, or remove them if !map
        }
        // etc
    

    Now either put a switch in the code, or comment/uncomment, or use a build script to switch, or whatever your current process is for switching between dev and production code:

        var kmlPath = "/my.kml";
        var kmlLayer =  MyProject.LOCAL_KML ?
            new MyProject.KmlLayer(MyProject.LOCAL_KML_HOST + kmlPath) :
            new google.maps.KmlLayer(MyProject.PRODUCTION_KML_HOST + kmlPath);
        kmlLayer.setMap(myMap);
    

    If, on the other hand, you need all of the functionality in the Google KmlLayer, or you want to make sure things work with the production setup, or you don't want to bother stubbing out the functionality Google provides, then you'll need to upload it to a publicly available server, so that Google can do its server-side processing.

    Aside from the obvious options (FTP, a command-line script to upload your new KML file, etc), most of which require you to do something manually before you load your map page, you might consider building the update into the page you're loading. Depending on the platform you're using, this might be easier to do on the back-end or the front-end; the key would be to have a script on your public server that would allow the KML to be updated:

    1. Get KML string from request.POST
    2. Validate the KML string (just so you aren't opening your server to attacks)
    3. Write to a single file, e.g. "my.kml"

    Then, when you view your map page, update the remote KML based on the data from localhost. Here's a client-side version, using jQuery:

    // again, you'd probably have a way to kill this block in production
    if (MyProject.UPDATE_KML_FROM_LOCALHOST) {
        // get localhost KML
        $.get(MyProject.LOCAL_KML_HOST + kmlPath, function(data) {
            // now post it to the remote server
            $.post(
                MyProject.DEV_KML_HOST + '/update_kml.php', 
                { kml: data }, 
                function() {
                    // after the post completes, get the KML layer from Google
                    var kmlLayer new google.maps.KmlLayer(MyProject.DEV_KML_HOST + kmlPath);
                    kmlLayer.setMap(myMap);
                }
            );
        })
    }
    

    Admittedly, there are a lot of round-trips here (page -> localhost, page -> remote server, Google -> remote server, Google -> page), so this is going to be slow. But it would allow you to have Google's code properly render dynamic KML data produced on localhost, without having to take a separate manual step every time you reload the page.

    0 讨论(0)
  • 2020-12-04 19:12

    Definitely, Google Maps KmlLayer is designed for you to send your data to them. https://developers.google.com/maps/documentation/javascript/kml

    Have a look the following log.

    //console
    var src = 'https://developers.google.com/maps/documentation/javascript/examples/kml/westcampus.kml';
    
    var kmlLayer = new google.maps.KmlLayer(src, {
      suppressInfoWindows: true,
      preserveViewport: false,
      map: your_gmap_object
    });
    

    Creating Marker, Polygon, they are all browser side parsing and rendering.

    As you can see from next network log, KmlLayer class send source URL to Google Server to parse it and (do something in their end) and send the parsed result back to your browser to render.

    //REQUEST from browser
    
    https://maps.googleapis.com/maps/api/js/KmlOverlayService.GetOverlays?1shttps%3A%2F%2Fdevelopers.google.com%2Fmaps%2Fdocumentation%2Fjavascript%2Fexamples%2Fkml%2Fwestcampus.kml&callback=_xdc_._lidt3k&key=AIzaSyBeLTP20qMgxsQFz1mwLlzNuhrS5xD_a_U&token=103685
    
    //RESPONSE from google server
    
    /**/_xdc_._lidt3k && _xdc_._lidt3k( [0,"kml:cXOw0bjKUSmlnTN2l67v0Sai6WfXhSSWuyNaDD0mAzh6xfi2fYnBo78Y2Eg","|ks:;dc:tg;ts:51385071|kv:3|api:3",...
    ["KmlFile"],[[37.423017,-122.0927],[37.424194,-122.091498]],[["g74cf1503d602f2e5"],["g58e8cf8fd6da8d29"],["ge39d22e72437b02e"]],1,[["client","2"]],-21505,[["ks",";dc:tg;ts:51385071"],["kv","3"],["api","3"]]] )
    

    As @capdragon mentioned above, it would be better parse KML by yourself.

    UPDATE

    Here is compact KML parser code. This only for google.maps Marker and Polygon.

    html

    <input type='file' accept=".kml,.kmz" onchange="fileChanged()">
    

    script, I used typescript but it is pretty same with javascript

      file: any
      fileChanged(e) {
        this.file = e.target.files[0]
        this.parseDocument(this.file)
      }
      parseDocument(file) {
        let fileReader = new FileReader()
        fileReader.onload = async (e: any) => {
          let result = await this.extractGoogleCoords(e.target.result)
    
          //CREATE MARKER OR POLYGON WITH result here
          console.log(result)
    
        }
        fileReader.readAsText(file)
      }
    
      async extractGoogleCoords(plainText) {
        let parser = new DOMParser()
        let xmlDoc = parser.parseFromString(plainText, "text/xml")
        let googlePolygons = []
        let googleMarkers = []
    
        if (xmlDoc.documentElement.nodeName == "kml") {
    
          for (const item of xmlDoc.getElementsByTagName('Placemark') as any) {
            let placeMarkName = item.getElementsByTagName('name')[0].childNodes[0].nodeValue.trim()
            let polygons = item.getElementsByTagName('Polygon')
            let markers = item.getElementsByTagName('Point')
    
            /** POLYGONS PARSE **/        
            for (const polygon of polygons) {
              let coords = polygon.getElementsByTagName('coordinates')[0].childNodes[0].nodeValue.trim()
              let points = coords.split(" ")
    
              let googlePolygonsPaths = []
              for (const point of points) {
                let coord = point.split(",")
                googlePolygonsPaths.push({ lat: +coord[1], lng: +coord[0] })
              }
              googlePolygons.push(googlePolygonsPaths)
            }
    
            /** MARKER PARSE **/    
            for (const marker of markers) {
              var coords = marker.getElementsByTagName('coordinates')[0].childNodes[0].nodeValue.trim()
              let coord = coords.split(",")
              googleMarkers.push({ lat: +coord[1], lng: +coord[0] })
            }
          }
        } else {
          throw "error while parsing"
        }
    
        return { markers: googleMarkers, polygons: googlePolygons }
    
      }
    

    output

    markers: Array(3)
    0: {lat: 37.42390182131783, lng: -122.0914977709329}
    ...
    
    polygons: Array(1)
    0: Array(88)
    0: {lat: -37.79825999283025, lng: 144.9165994157198}
    ...
    
    0 讨论(0)
提交回复
热议问题