web-dev-qa-db-ja.com

Googleマップを使用してローカル.kmlファイルを読み込みますか?

ローカルのkmlファイル(Googleのドキュメントから借用)を読み込むhello worldプログラムを作成しました。

var ctaLayer = new google.maps.KmlLayer("http://localhost:8080/kml/cta.kml");

これは機能しません(何もロードされません)。

ただし、その行を次のように変更すると:

  var ctaLayer = new google.maps.KmlLayer("http://gmaps-samples.googlecode.com/svn/trunk/ggeoxml/cta.kml");

正しくロードされます。両方のkmlファイルは同一です。自分でサービスを提供するときにロードするには、何をする必要がありますか? (絶対パスと相対パスの両方を試しましたが、使用しているパスが正しいことを知っています...)

また、アプリケーションサーバーの構成ファイルに正しいMIMEタイプを追加しました。

<mime-mapping>
    <extension>kml</extension>
<mime-type>application/vnd.google-earth.kml+xml</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>kmz</extension>
    <mime-type>application/vnd.google-earth.kmz</mime-type>
</mime-mapping>

しかし、まだロードされません。

私はグーグルの docs でこれを見つけました:

Google Maps APIは、地理情報を表示するためのKMLおよびGeoRSSデータ形式をサポートしています。これらのデータ形式は、KmlLayerオブジェクトを使用して地図に表示されます。KmlLayerオブジェクトのコンストラクターは、公開されているKMLまたはGeoRSSファイルのURLを取得します。

だから私がやろうとしていることは、not公にアクセス可能なURLからkmlにサービスを提供することなく可能だと思います...誰かが他の方法で証明できない限り

51
hddd

KMLはローカルマシン上にあるためアクセスできず、Googleはlocalhost:8080へのアクセス方法がわからないためKMLにアクセスできません。

55
Martin Murphy

残念ながら、「localhost」は使用できません。次の2つの選択肢があります。

  1. kmlを公開ドメインに配置します。 (Googleがアクセスできない場合、機能しません)
  2. 基本的にはgoogleが行うことを行いますが、パーサーJSファイルをダウンロードしてホストすることができるgeoxml3を使用します。 LOCALHOST KMLを読み込んで解析することができます(JSON経由でアクセス可能なオブジェクト)( http://code.google.com/p/geoxml3/ )。

選択#1は、KMLがバックグラウンドでgoogleに送信され、地図上にレンダリングされるため、防衛契約に携わる人や機密情報を扱う人には選択肢ではないかもしれません。

39
capdragon

このウェブサイト display-kml.appspot.com では、KMLファイル全体をコピーしてウェブサイトに貼り付ける必要があります。または、 Dropbox を使用して、パブリックフォルダーを使用してKMLファイルをホストできます。 Dropboxのパブリックフォルダー内には、URLをコピーできる右クリックコンテキストメニューがあります。

Appspot Webサイトには不安定な歴史があります。 2019年1月現在、ウェブサイトは機能しているようです。

  1. http://display-kml.appspot.com/
  2. https://www.dropbox.com/
17
Ragaar

間違いなく、Google Maps KmlLayerはデータを送信するように設計されています。 https://developers.google.com/maps/documentation/javascript/kml

次のログをご覧ください。

//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
});

Marker、Polygonを作成すると、それらはすべてブラウザー側の解析およびレンダリングです。

次のネットワークログからわかるように、KmlLayerクラスはソースURLをGoogleサーバーに送信して解析し、(最後に何かをして)解析したものを送信します結果をブラウザに戻してレンダリングします。

//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"]]] )

上記の@capdragonのように、KMLを自分で解析する方が良いでしょう

[〜#〜] update [〜#〜]

これは、コンパクトなKMLパーサーコードです。これは、google.mapsマーカーとポリゴンのみ。

html

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

スクリプト、TypeScriptを使用しましたが、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 }

  }

出力

markers: Array(3)
0: {lat: 37.42390182131783, lng: -122.0914977709329}
...

polygons: Array(1)
0: Array(88)
0: {lat: -37.79825999283025, lng: 144.9165994157198}
...
1
John