使用多个图层中的kmz文件更新Google地图

时间:2014-08-22 01:31:38

标签: javascript google-maps-api-3 google-apps-script google-drive-api kmz

下个九月我会骑自行车旅行三个月。我将使用带有Motion-X GPS app的iPhone来记录每天的曲目。这个旅程打算引起一些公众的注意,因此我正在建立一个使用Squarespace的网站,我打算在Google地图上每天上传自行车道。我不能花太多时间处理文件或执行手动任务。一切都需要由一个事件触发。每天。到目前为止一切都很好。

Motion-X GPS记录GPS轨迹并允许通过电子邮件共享它们。通过电子邮件发送的文件是一个gpx文件和一个kmz文件作为单个电子邮件正文中的附件。这是我的触发器。

在我的网站上,我设法加载了Google地图(使用Google Maps Javascript Api)并绘制了航点和KmlLayers。我还运行了Google云端硬盘脚本,可自动下载带有kmz或gpx扩展名的电子邮件附件,并将其保存在Google云端硬盘文件夹中。我还可以通过另一个脚本检索这些文件的永久链接。我想我甚至可以弄清楚如何在每次将新的KMZ文件添加到文件夹时在网站上为我的javascript代码添加新图层,但我还没有那么远。

这是梦魇开始的地方。

第一种方法。我可以使用KmlLayer在我的地图上绘制一个KMZ文件。没问题。但谷歌地图有大约15-20层的限制,旅程持续约100天,每天增加一个新的层。这意味着当达到限制时,地图上可能存在许多层并且可能是停电。由于很多人将访问该网站,我不希望这种情况发生。

第二个选项是拥有一个脚本:

  1. 解压缩KMZ。
  2. 将解压缩的KML保存在另一个文件夹中。
  3. 将所有KML合并为一个KML。
  4. 我无法克服第1步。我尝试使用脚本在驱动器上解压缩我的KMZ文件,但我无法解决。这是我在测试时使用的代码:

    function unZip() {
    
     var kmzs = DriveApp.getFilesByType('application/vnd.google-earth.kmz');
     while (kmzs.hasNext()){
      var kmz = kmzs.next();
      var zipBlob = kmz.getBlob();
      var unzipBlob = Utilities.unzip(zipBlob);
      var unzipBlobName = unzipBlob[1].getName();
    
      Logger.log(unzipBlobName);
     }
    }
    

    这会在“unzipBlob”上引发错误。除非我找到解压缩然后合并文件的选项,否则此路径将在此处结束。

    我也尝试了zipextractor,但它不能识别kmz文件是不可解压的。我甚至将.kmz文件重命名为.zip,没有成功。

    https://github.com/googledrive/zipextractor

    第三个选项是绘制gpx文件。经过几个小时的谷歌搜索后,我发现此链接在Google地图上绘制了一个gpx文件:

    http://www.jacquet80.eu/blog/post/2011/02/Display-GPX-tracks-using-Google-Maps-API

    这是代码段:

     $.ajax({
        type: "GET",
        url: "URL to the GPX file",
        dataType: "xml",
        success: function(xml) {
        var points = [];
        var bounds = new google.maps.LatLngBounds ();
        $(xml).find("trkpt").each(function() {
          var lat = $(this).attr("lat");
          var lon = $(this).attr("lon");
          var p = new google.maps.LatLng(lat, lon);
          points.push(p);
          bounds.extend(p);
        });
    
        var poly = new google.maps.Polyline({
          // use your own style here
          path: points,
          strokeColor: "#FF00AA",
          strokeOpacity: .7,
          strokeWeight: 4
        });
    
        poly.setMap(map);
    
        // fit bounds to track
        map.fitBounds(bounds);
       }
       });
    

    但是,我无法使用该代码绘制任何Google Drive gpx文件。出现灰色块而不是地图,或者如果我尝试同时绘制其他图层,则其他图层将可见,但gpx图层不会。我想这与同源策略有关,因为我指的是Google,而我的是Squarespace。

    此时,在三种不同的解决方案上达到了死胡同,经过数小时的搜索和尝试,我看不到更多。我真的很感激有关这个问题的任何帮助。自9月9日开始旅程以来,我的时间紧迫。再次,任何暗示,建议或评论都会非常感激。

1 个答案:

答案 0 :(得分:2)

我找到了解决方案。

我依赖了几个来源,并以某种方式碰到了Nesting KMZ files

这给了我一个线索。我尝试了不同的文件和选项,但结果如下:

  1. 我使用this script自动将.XTZ文件从MotionX-GPS上传到Google云端硬盘中的文件夹。
  2. 我在同一个文件夹中有一个file.kml文件,它有一个嵌套结构,指向带有NetworkLink的.kmz文件。
  3. 我有一个Chrome App在云中运行脚本来同步Dropbox和Google Drive。出于某种原因,Drive中的file.kml永久链接不起作用,但Dropbox公共文件夹中的那个很好。 Google Maps Javascript API中的kmlLayer链接到dropbox中的file.kml。
  4. 最后,我每小时运行一个独立的Google脚本,根据我的云端硬盘文件夹中存在的.kmz替换file.kml的内容。我可以删除,添加或修改名称,但只要kmz文件在我的track文件夹中,它们就会嵌套在file.kml中。
  5. 就是这样。这是我的脚本代码。用您的数据替换大写例。可能有一种更简单或更聪明的方法,但这就完成了工作。

    //This function reads kmz files inside an specific folder in Google Drive and fills "file.kml" with a list of Networklinks for those files. The links refer to a mirror in a synced dropbox public folder
    function kmlFileSetContent(){
        var contentHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http://www.opengis.net/kml/2.2\"><Document>"
        var contentFooter ="</Document></kml>";
        var fileHeader = "<NetworkLink> <Link><href>YOUR_DROPBOX_PERMALINK_FOR_PUBLIC_FOLDER";
        var fileFooter = "</href></Link></NetworkLink>"
        var kmzFolder = DriveApp.getFolderById("YOUR_FOLDER_ID");
        var kmzFiles = kmzFolder.getFilesByType('application/vnd.google-earth.kmz');
        while(kmzFiles.hasNext()){
            var kmzFile = kmzFiles.next();
            var fileName = kmzFile.getName();
            var networkLink = fileHeader+fileName+fileFooter;
            var networkLinkAll = networkLinkAll+ networkLink;
        }
        var newContent = contentHeader+networkLinkAll+contentFooter;
        Logger.log(newContent);
        var kmlFile = DriveApp.getFileById("YOUR_FILEKML_ID");
        kmlFile.setContent(newContent);
    
    }