Leaflet - 从静态文件中获取数据并 API 调用以构建等值线图
Leaflet - get data from static file and API call to build a choropleth map
我有 2 个数据源 JSON 数据。
一个是静态文件,包含如下国家边界:
静态文件
var worldboundaries = {"type":"FeatureCollection","features":
[{"type":"Feature","id":"ALB","properties":{"name":"Albania"},"geometry":{"type":"Polygon","coordinates":[[[20.590247,41.855404],[20.463175,41.515089],[20.605182,41.086226],[21.02004,40.842727],[20.99999,40.580004],[20.674997,40.435],[20.615,40.110007],[20.150016,39.624998],[19.98,39.694993],[19.960002,39.915006],[19.406082,40.250773],[19.319059,40.72723],[19.40355,41.409566],[19.540027,41.719986],[19.371769,41.877548],[19.304486,42.195745],[19.738051,42.688247],[19.801613,42.500093],[20.0707,42.58863],[20.283755,42.32026],[20.52295,42.21787],[20.590247,41.855404]]]}},
{"type":"Feature","id":"ARE","properties":{"name":"United Arab Emirates"},"geometry":{"type":"Polygon","coordinates":[[[51.579519,24.245497],[51.757441,24.294073],[51.794389,24.019826],[52.577081,24.177439],[53.404007,24.151317],[54.008001,24.121758],[54.693024,24.797892],[55.439025,25.439145],[56.070821,26.055464],[56.261042,25.714606],[56.396847,24.924732],[55.886233,24.920831],[55.804119,24.269604],[55.981214,24.130543],[55.528632,23.933604],[55.525841,23.524869],[55.234489,23.110993],[55.208341,22.70833],[55.006803,22.496948],[52.000733,23.001154],[51.617708,24.014219],[51.579519,24.245497]]]}},
....
其中一个包含该国家/地区应使用的 fillColor 的密度信息,其中 "count" 是我需要的值。这是一个 kimonolabs api 并通过 $AJAX 请求调用:
API回答
{"name":"myapi","count":51,"frequency":"Daily","version":109,"newdata":true,"lastrunstatus":"success","thisversionstatus":"success","nextrun":"Fri Sep 25 2015 11:29:40 GMT+0000 (UTC)","thisversionrun":"Thu Sep 24 2015 11:29:40 GMT+0000 (UTC)",
"results":
{"myapi":[{"name":{"href":"http://www.somelink.com","text":"Albania"},"count":"1","index":1,"url":"http://www.somelink.com"},
{"name":{"http://www.somelink.com","text":"United Arab Emirates"},"count":"30","index":2,"url":"http://www.somelink.com"},
...
对于地图,我遵循以下指南:tutorial
JS文件包含API调用
//Building the map
var map = L.map('map').setView([37.8, -96], 4);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=' + mapboxAccessToken, {
id: 'mapbox.light',
attribution: ...
}).addTo(map);
//Color function
function getColor(d) {
return d > 1000 ? '#800026' :
d > 500 ? '#BD0026' :
d > 200 ? '#E31A1C' :
d > 100 ? '#FC4E2A' :
d > 50 ? '#FD8D3C' :
d > 20 ? '#FEB24C' :
d > 10 ? '#FED976' :
'#FFEDA0';
}
//Style function
function style(feature) {
return {
fillColor: getColor(feature.properties.density),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}
//Load static file
L.geoJson(worldBoundaries, {style: style}).addTo(map);
//AJAX call to API
$.ajax({
"url":"https://www.kimonolabs.com/api/myapi,
"crossDomain": true,
"dataType": "jsonp",
//Make a call to the Kimono API following the "url"
'success': function(response){
//Do some stuff, place some markers
var collection = response.results.myapi;
//collection.count is what I need from here
......
编辑
为此添加了一个 plunker:http://plnkr.co/edit/98OiwqYBr7pP478tJAtl?p=preview
getColor(feature.properties.density)
本质上是我的问题。 Leaflet 正确地绘制了国家边界层,但是 "density" 信息来自 ajax api 调用并且不包含在 wordlboundaries 数组中。 我如何告诉它查看 api 结果并使用正确国家的 "count" 值来适当地为地图着色? 我如何访问变量来自稍后在另一个 function/do 中的 ajax 调用 我必须将此中的每个函数放入 ajax 调用中?
国家边界文件包含世界上 api 请求不包含所有国家/地区的所有国家/地区。
感谢您的想法!
在成功使用数据之前,需要解决一些问题。如果您将数据记录到控制台以查看您正在使用的内容,这些将更加清晰。定义边界层后,尝试将以下内容放入 AJAX 成功函数中:
console.log(response);
console.log(loadboundaries);
首先,您会看到 API 正在返回德语数据。没有名为 response.results.beerorigin
的字段(正如您的脚本正在查找的那样),而是一个名为 response.results.bierherkunft
的字段。计数数据位于名为 response.results.bierherkunft[i].count
的字段中(其中 i 是 0-52 的对象索引),国家/地区名称位于 response.results.bierherkunft[i].name.text
.
中
这给我们带来了第二个问题:API 返回的国家/地区名称也是德语,而您的 GeoJSON 文件包含英语国家/地区名称。因此,如果您想匹配两个文件中的国家/地区,您需要获取一个 GeoJSON 文件,其中的国家/地区名称已经是德语,或者手动翻译 GeoJSON 文件中的名称(或者,也许更好,添加一个新的 属性 喜欢 name_de
来保存翻译后的名字,以防你仍然使用这些英文名字)。当然,如果有一个选项可以用英文从 API 请求数据,那将是解决该问题的最简单方法。
一旦您拥有了所有使用相同语言的数据,您将需要按名称将啤酒数据与您的 loadboundaries
图层连接起来。这可以通过在创建图层时使用 onEachFeature
来调用一个函数来完成,该函数搜索 feature.properties.name_de
和 response.results.bierherkunft[i].name.text
之间的匹配项,然后为计数添加一个新的 属性数据。因此,假设您已将 response.results.bierherkunft
分配给 collection
,它会像这样:
function onEachFeature(feature, layer) {
feature.properties.density = 0;
for (var i in collection) {
if(collection[i].name.text === feature.properties.name_de) {
feature.properties.density = parseInt(collection[i].count);
}
}
}
parseInt
是必需的,因为 count
字段存储为文本,而 getColor
需要一个数字。可以使用 setStyle
方法应用样式,如下所示:
var loadboundaries = L.geoJson(worldboundaries, {onEachFeature: onEachFeature});
map.on('load', loadboundaries.addTo(map).setStyle(function (feature) {
return {
fillColor: getColor(feature.properties.density),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}));
这里有一个有效的 plunk:
我有 2 个数据源 JSON 数据。 一个是静态文件,包含如下国家边界:
静态文件
var worldboundaries = {"type":"FeatureCollection","features":
[{"type":"Feature","id":"ALB","properties":{"name":"Albania"},"geometry":{"type":"Polygon","coordinates":[[[20.590247,41.855404],[20.463175,41.515089],[20.605182,41.086226],[21.02004,40.842727],[20.99999,40.580004],[20.674997,40.435],[20.615,40.110007],[20.150016,39.624998],[19.98,39.694993],[19.960002,39.915006],[19.406082,40.250773],[19.319059,40.72723],[19.40355,41.409566],[19.540027,41.719986],[19.371769,41.877548],[19.304486,42.195745],[19.738051,42.688247],[19.801613,42.500093],[20.0707,42.58863],[20.283755,42.32026],[20.52295,42.21787],[20.590247,41.855404]]]}},
{"type":"Feature","id":"ARE","properties":{"name":"United Arab Emirates"},"geometry":{"type":"Polygon","coordinates":[[[51.579519,24.245497],[51.757441,24.294073],[51.794389,24.019826],[52.577081,24.177439],[53.404007,24.151317],[54.008001,24.121758],[54.693024,24.797892],[55.439025,25.439145],[56.070821,26.055464],[56.261042,25.714606],[56.396847,24.924732],[55.886233,24.920831],[55.804119,24.269604],[55.981214,24.130543],[55.528632,23.933604],[55.525841,23.524869],[55.234489,23.110993],[55.208341,22.70833],[55.006803,22.496948],[52.000733,23.001154],[51.617708,24.014219],[51.579519,24.245497]]]}},
....
其中一个包含该国家/地区应使用的 fillColor 的密度信息,其中 "count" 是我需要的值。这是一个 kimonolabs api 并通过 $AJAX 请求调用:
API回答
{"name":"myapi","count":51,"frequency":"Daily","version":109,"newdata":true,"lastrunstatus":"success","thisversionstatus":"success","nextrun":"Fri Sep 25 2015 11:29:40 GMT+0000 (UTC)","thisversionrun":"Thu Sep 24 2015 11:29:40 GMT+0000 (UTC)",
"results":
{"myapi":[{"name":{"href":"http://www.somelink.com","text":"Albania"},"count":"1","index":1,"url":"http://www.somelink.com"},
{"name":{"http://www.somelink.com","text":"United Arab Emirates"},"count":"30","index":2,"url":"http://www.somelink.com"},
...
对于地图,我遵循以下指南:tutorial
JS文件包含API调用
//Building the map
var map = L.map('map').setView([37.8, -96], 4);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=' + mapboxAccessToken, {
id: 'mapbox.light',
attribution: ...
}).addTo(map);
//Color function
function getColor(d) {
return d > 1000 ? '#800026' :
d > 500 ? '#BD0026' :
d > 200 ? '#E31A1C' :
d > 100 ? '#FC4E2A' :
d > 50 ? '#FD8D3C' :
d > 20 ? '#FEB24C' :
d > 10 ? '#FED976' :
'#FFEDA0';
}
//Style function
function style(feature) {
return {
fillColor: getColor(feature.properties.density),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}
//Load static file
L.geoJson(worldBoundaries, {style: style}).addTo(map);
//AJAX call to API
$.ajax({
"url":"https://www.kimonolabs.com/api/myapi,
"crossDomain": true,
"dataType": "jsonp",
//Make a call to the Kimono API following the "url"
'success': function(response){
//Do some stuff, place some markers
var collection = response.results.myapi;
//collection.count is what I need from here
......
编辑
为此添加了一个 plunker:http://plnkr.co/edit/98OiwqYBr7pP478tJAtl?p=preview
getColor(feature.properties.density)
本质上是我的问题。 Leaflet 正确地绘制了国家边界层,但是 "density" 信息来自 ajax api 调用并且不包含在 wordlboundaries 数组中。 我如何告诉它查看 api 结果并使用正确国家的 "count" 值来适当地为地图着色? 我如何访问变量来自稍后在另一个 function/do 中的 ajax 调用 我必须将此中的每个函数放入 ajax 调用中?
国家边界文件包含世界上 api 请求不包含所有国家/地区的所有国家/地区。
感谢您的想法!
在成功使用数据之前,需要解决一些问题。如果您将数据记录到控制台以查看您正在使用的内容,这些将更加清晰。定义边界层后,尝试将以下内容放入 AJAX 成功函数中:
console.log(response);
console.log(loadboundaries);
首先,您会看到 API 正在返回德语数据。没有名为 response.results.beerorigin
的字段(正如您的脚本正在查找的那样),而是一个名为 response.results.bierherkunft
的字段。计数数据位于名为 response.results.bierherkunft[i].count
的字段中(其中 i 是 0-52 的对象索引),国家/地区名称位于 response.results.bierherkunft[i].name.text
.
这给我们带来了第二个问题:API 返回的国家/地区名称也是德语,而您的 GeoJSON 文件包含英语国家/地区名称。因此,如果您想匹配两个文件中的国家/地区,您需要获取一个 GeoJSON 文件,其中的国家/地区名称已经是德语,或者手动翻译 GeoJSON 文件中的名称(或者,也许更好,添加一个新的 属性 喜欢 name_de
来保存翻译后的名字,以防你仍然使用这些英文名字)。当然,如果有一个选项可以用英文从 API 请求数据,那将是解决该问题的最简单方法。
一旦您拥有了所有使用相同语言的数据,您将需要按名称将啤酒数据与您的 loadboundaries
图层连接起来。这可以通过在创建图层时使用 onEachFeature
来调用一个函数来完成,该函数搜索 feature.properties.name_de
和 response.results.bierherkunft[i].name.text
之间的匹配项,然后为计数添加一个新的 属性数据。因此,假设您已将 response.results.bierherkunft
分配给 collection
,它会像这样:
function onEachFeature(feature, layer) {
feature.properties.density = 0;
for (var i in collection) {
if(collection[i].name.text === feature.properties.name_de) {
feature.properties.density = parseInt(collection[i].count);
}
}
}
parseInt
是必需的,因为 count
字段存储为文本,而 getColor
需要一个数字。可以使用 setStyle
方法应用样式,如下所示:
var loadboundaries = L.geoJson(worldboundaries, {onEachFeature: onEachFeature});
map.on('load', loadboundaries.addTo(map).setStyle(function (feature) {
return {
fillColor: getColor(feature.properties.density),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}));
这里有一个有效的 plunk: