问题
I'm using JSON data to populate JVectorMaps (and others) directly. Up-to-date stats for most common indicators are available via json online - so this script should let you can pluck whatever data that you like quickly and easily. I just haven't quite figured out the formatting code yet as I am very new to JQuery & JS. I put a question mark where I'm stumped.
Ideally, the fetch and Data scripts could take an ind_id variable and label that presented any indicator on the Vector Map, and not just the one GDP (NY.GDP.MKTP.CD) indicator I used as an example here.
document.addEventListener('DOMContentLoaded', () => {
console.log("loaded")
fetchCountryData()
})
function fetchCountryData () {
fetch('http://api.worldbank.org/v2/country/all/indicator/NY.GDP.MKTP.CD?format=json&mrv=1&per_page=300)
//
.then(resp => resp.json())
.then(data => {
let country.id = data[1]
let value = data[1]
create-GDP-Data(country.id,value)
})
}
function create-GDP-Data(country.id,value){
let gdpData = ?
}
$('#world-map-gdp').vectorMap({
map: 'world_mill',
series: {
regions: [{
values: gdpData,
scale: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial'
}]
},
onRegionTipShow: function(e, el, code){
el.html(el.html()+' (GDP - '+gdpData[code]+')');
}
});
GDP Data (gdpData) should be formatted as follows:
var gdpData = {
"AF": 16.63,
"AL": 11.58,
"DZ": 158.97,
...
};
回答1:
You are aware that the requested dataset is returning back a somewhat different data structure as the one needed for jVectorMap
. So, what You need is a remapper from the incoming data to the latter.
To make this approach more flexible, my proposal is to use a straightforward remapper function, where You can pass-in the name of the incoming field, and receive back the value for that.
Please, see the comments inside my proposal below for further information:
DEMO: Dynamic loading of a jVectorMap region dataset
$(function() {
/* Handler for jQuery .ready() */
function mapper(data, key) {
/* Deep search for a key, return the value found. */
var keys = key.split('.'), value = data[keys.shift()];
for(var i=0, l=keys.length; i<l; i++) {value = value[keys[i]]}
return value;
}
function showMapValues(schema, map, values, min, max) {
var regions = map.series.regions[0];
/* Reset the scale min & max, allow recomputation. */
regions.params.min = min;
regions.params.max = max;
regions.setValues(values.regions);
map.dataSetName = schema.dataSetName;
map.dataSetFormat = schema.dataSetFormat;
}
function remapData(schema, map, data) {
var values = {regions: {}, markers: {}};
/* Loop over the returned dataset and invoke remap. */
$.each(data, function(i, item) {
var code = mapper(item, schema.countryCodeField),
value = mapper(item, schema.countryValueField) || 0;
/* Find out if this is a valid region inside the map. */
var isRegionCode = typeof map.regions[code] !== 'undefined';
/* Find out if this is a valid marker inside the map. */
var isMarkerCode = typeof map.markers[code] !== 'undefined';
/* Fill two separate datasets for regions & markers. */
if(isRegionCode) values.regions[code] = value;
if(isMarkerCode) values.markers[code] = value;
});
return values;
}
function fetchAlternateCountryData(schema, map) {
$.ajax({
url: schema.alternate,
dataType: 'json',
success: function(result) {
var dataSet = result[schema.dataSetIndex];
/* Dynamically update the map with the new local data */
showMapValues(schema, map, remapData(schema, map, dataSet));
}
});
}
function fetchCountryData(schema, map) {
$.ajax({
url: schema.url,
dataType: 'json',
data: schema.params,
success: function(result) {
var dataSet = result[schema.dataSetIndex];
if(dataSet) {
/* Dynamically update the map with the new remote data */
showMapValues(schema, map, remapData(schema, map, dataSet));
} else {
/* Manage "Invalid value" response */
fetchAlternateCountryData(schema, map);
}
},
error: function(request, textStatus, errorThrown) {
/* Manage some other trappable ajax errors */
fetchAlternateCountryData(schema, map);
}
});
}
var worldMap = new jvm.Map({
map: 'world_mill_en',
container: $('#world-map'),
zoomOnScroll: true,
regionsSelectable: false,
backgroundColor: "aliceblue",
markers: [], /* Initialize the map with empty markers */
series: {
regions: [{
values: {}, /* Initialize the map with empty region values */
scale: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial'
}],
/* Initialize the map with empty marker values */
markers: [{attribute: 'fill', scale: {}, values: []}]
},
onRegionTipShow: function(e, el, code){
var value = worldMap.series.regions[0].values[code],
formattedValue = new Intl.NumberFormat('en-US', worldMap.dataSetFormat).format(value);
el.text(el.text() + ' (' + worldMap.dataSetName + ': ' + formattedValue + ')');
}
});
/* Define the data type & the location of the relevant fields inside the incoming data */
var schema = {
url: 'https://api.worldbank.org/v2/country/all/indicator/NY.GDP.MKTP.CD',
params: 'format=json&mrv=1&per_page=300',
alternate: '/ind_MapData',
dataSetName: 'GDP',
dataSetFormat: {style: 'currency', currency: 'USD'},
dataSetIndex: 1,
countryCodeField: 'country.id',
countryValueField: 'value'
};
fetchCountryData(schema, worldMap);
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jvectormap@2.0.4/jquery-jvectormap.min.css" type="text/css">
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jvectormap@2.0.4/jquery-jvectormap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jvectormap@2.0.4/tests/assets/jquery-jvectormap-world-mill-en.js"></script>
</head>
<body>
<div id="world-map" style="width: 600px; height: 400px"></div>
</body>
</html>
Moreover:
Please pay attention: the original world map from jVectorMap
doesn't include some tiny countries like Singapore, Liechtenstein and so on. They are simply too small, You would need to zoom-in a lot. The preferred solution for this problem is to place additional markers at their location. After that, You can set the incoming data for that markers accordingly.
See my answer here: jVectorMap - How to add marker dynamically
BTW, thanks to bjornd for the great jVectorMap.
来源:https://stackoverflow.com/questions/61163371/using-jquery-and-online-json-data-to-populate-jvectormaps