javascript Google Maps API 和 KML 文件 LocalHost 开发选项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6092110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google Maps API and KML File LocalHost Development Options
提问by ahsteele
The Google Maps JavaScript version 3 API library documentation clearly explains:
Google Maps JavaScript 版本 3 API库文档清楚地解释了:
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 accessibleKML or GeoRSS file.
Google Maps API 支持用于显示地理信息的 KML 和 GeoRSS 数据格式。这些数据格式使用 KmlLayer 对象显示在地图上,该对象的构造函数采用可公开访问的KML 或 GeoRSS 文件的 URL 。
There are even several Stack Overflow questions about how to load local data:
甚至还有几个关于如何加载本地数据的 Stack Overflow 问题:
Some of the answers have pointed to third party libraries which can parse KML locally without the file needing to be public:
一些答案指向第三方库,它们可以在本地解析 KML,而无需公开文件:
And while these solutions are good if you have a need to keep your data private, I simply want to make development easier. When running locally I obviously cannot parse my KML and therefore lose functionality that I am trying to test. I've posted a single generic KML file on a publicly available site, but then have to have different development code to render one thing vs. something else when running for real.
如果您需要将数据保密,这些解决方案是很好的,但我只是想让开发更容易。在本地运行时,我显然无法解析我的 KML,因此失去了我试图测试的功能。我在一个公开可用的站点上发布了一个通用 KML 文件,但是在真正运行时必须使用不同的开发代码来呈现一件事与另一件事。
What are my options for local development to render what would be publicly available dynamically generated KML files?
我有哪些本地开发选项可以呈现公开可用的动态生成的 KML 文件?
采纳答案by nrabinowitz
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 displayingthe KML features. In this case, I'd probably set up a stub class, like this:
如果您想处理本地数据,而不涉及可公开访问的网络服务器,则需要使用基于 javascript 的方法来解析 KML 并将其加载到地图上。虽然这不会完全复制 Google 的功能,但如果您只关心显示KML功能,它对于初始开发来说可能已经足够了。在这种情况下,我可能会设置一个存根类,如下所示:
// 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.
另一方面,如果您需要 Google 中的所有功能KmlLayer
,或者您想确保一切都适用于生产设置,或者您不想打扰 Google 提供的功能,那么您将需要将其上传到公开可用的服务器,以便 Google 可以进行服务器端处理。
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:
除了明显的选项(FTP、用于上传新 KML 文件的命令行脚本等),其中大多数选项要求您在加载地图页面之前手动执行某些操作,您可能会考虑将更新构建到您的页面中重新加载。根据您使用的平台,这在后端或前端可能更容易实现;关键是在您的公共服务器上有一个允许更新 KML 的脚本:
- Get KML string from request.POST
- Validate the KML string (just so you aren't opening your server to attacks)
- Write to a single file, e.g. "my.kml"
- 从 request.POST 获取 KML 字符串
- 验证 KML 字符串(这样您就不会打开服务器受到攻击)
- 写入单个文件,例如“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:
然后,当您查看地图页面时,根据来自 的数据更新远程 KML localhost
。这是一个使用 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.
诚然,这里有很多往返(页面 -> localhost,页面 -> 远程服务器,谷歌 -> 远程服务器,谷歌 -> 页面),所以这会很慢。但它允许您让 Google 的代码正确呈现在本地主机上生成的动态 KML 数据,而无需在每次重新加载页面时执行单独的手动步骤。
回答by John
Definitely, Google Maps KmlLayer is designed for you to send your data to them. https://developers.google.com/maps/documentation/javascript/kml
毫无疑问,Google Maps KmlLayer 旨在让您将数据发送给他们。 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.
创建Marker、Polygon,都是浏览器端解析渲染。
As you can see from next network log, KmlLayer class send source URL to Google Serverto parse it and (do something in their end) and send the parsed result back to your browser to render.
正如您从下一个网络日志中看到的那样,KmlLayer 类将源 URL 发送到 Google Server以对其进行解析并(在他们的最后做一些事情)并将解析的结果发送回您的浏览器以进行渲染。
//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.
正如@capdragon 上面提到的,最好自己解析 KML。
UPDATE
更新
Here is compact KML parser code. This only for google.maps Marker and Polygon.
这是紧凑的 KML 解析器代码。这仅适用于 google.maps 标记和多边形。
html
html
<input type='file' accept=".kml,.kmz" onchange="fileChanged()">
script, I used typescript but it is pretty same with javascript
脚本,我使用了打字稿,但它与 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}
...