使用谷歌地图加载本地 .kml 文件?

发布于 2024-09-15 02:52:48 字数 1177 浏览 6 评论 0原文

我创建了一个 hello world 程序来加载本地 kml 文件(从 google 的文档借用):

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>

但它仍然无法加载。

我在谷歌的文档中找到了这个:

Google 地图 API 支持 KML 和 GeoRSS 数据格式来显示地理信息。这些数据格式使用 KmlLayer 对象显示在地图上,该对象的构造函数采用可公开访问的 KML 或 GeoRSS 文件的 URL。

所以我想如果不从可公开访问的 URL 提供 KML,我想要做的事情是不可能的......除非有人可以证明不是这样

I created a hello world program to load a local kml file (borrowed from google's docs):

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

This does not work (nothing gets loaded).

However, when I change that line to:

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

it loads properly. Both kml files are identical. What do I need to do to get it to load when serving it myself? (I tried both absolute and relative paths, and I know the paths I am using are correct...)

Also I added the correct mime type to my appserver's config file:

<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>

But it still doesn't load.

I found this in google's docs:

The Google Maps API supports the KML and GeoRSS data formats for displaying geographic information. These data formats are displayed on a map using a KmlLayer object, whose constructor takes the URL of a publicly accessible KML or GeoRSS file.

So I guess what I am trying to do is not possible without serving the kml from a publicly accessible url...unless someone can prove otherwise

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

药祭#氼 2024-09-22 02:52:48

KML 无法访问,因为它位于您的本地计算机上,而 google 无法访问它,因为它不知道如何访问 localhost:8080

The KML can't be accessed since it's on your local machine and google can't access that since it doesn't know how to get to localhost:8080

第七度阳光i 2024-09-22 02:52:48

不幸的是你不能使用“localhost”。您有两种选择:

  1. 将 kml 放在公共可用的域中。 (如果谷歌无法访问它,它将无法工作)
  2. 使用geoxml3,它基本上完成谷歌所做的事情,但允许您自己下载并托管解析器JS文件。它将允许您加载 LOCALHOST KML 并为您解析它(可通过 JSON 访问的对象) (http: //code.google.com/p/geoxml3/)。

对于那些从事国防合同和处理敏感信息的人来说,选择#1可能不是一个选择,因为 kml 在后台发送到谷歌并呈现在地图上。

Unfortunately you cannot use "localhost". You have two choices:

  1. place the kml on a publically available domain. (if google cannot access it, it won't work)
  2. Use geoxml3 which basically does what google does but allows you to downlaod and host the parser JS file youself. It will allow you to load a LOCALHOST KML and parse it out for you (objects accessible via JSON) (http://code.google.com/p/geoxml3/).

Choice #1 might not be an option for those working on defense contracts and deal with sensitive information as the kml is sent to google in the background and rendered on the map.

百变从容 2024-09-22 02:52:48

此网站 display-kml.appspot.com 要求您复制/粘贴整个 KML 文件进入网站。或者,您可以使用 Dropbox 通过公用文件夹托管 KML 文件。在公共 Dropbox 文件夹中,有一个右键单击上下文菜单,可让您复制 URL。

Update:

appspot 网站有不稳定的历史。截至 2019 年 1 月,该网站似乎正在运行。

REFERENCES:

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

This website, display-kml.appspot.com, requires that you copy/paste the entire KML file into the website. Alternatively, you can use Dropbox to host the KML file using your public folder. Within the public Dropbox folder, there is a right-click context menu that allows you to copy the URL.

Update:

The appspot website has a history of being unstable. As of January 2019, the website appears to be working.

REFERENCES:

  1. http://display-kml.appspot.com/
  2. https://www.dropbox.com/
泪眸﹌ 2024-09-22 02:52:48

当然,Google 地图 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

更新

这是紧凑的 KML 解析器代码。
这仅适用于 google.maps 标记和多边形。

html

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

非常相似

  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 }

  }

脚本,我使用了 typescript 但它与 javascript输出

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

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

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}
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文