GeoJSON
The Business Charts panel supports the world and USA GeoJSON maps. You can load additional maps dynamically.
Demo
Try the map on the dashboard in the edit mode.
Tutorial
You can watch the following video to better understand how to use GeoJSON maps.
Metrics with values
const requests = context.panel.data.series.map((s) => {
const names = s.fields.find((f) => f.name === "Metric").values;
const values = s.fields.find((f) => f.name === "Value (sum)").values;
return names.map((name, i) => {
return { name: name, value: values[i] };
});
})[0];
const min = Math.min(...requests.map((o) => o.value));
const max = Math.max(...requests.map((o) => o.value));
const labelValue = (max - min) / 4;
return {
animation: true,
backgroundColor: "transparent",
tooltip: {
trigger: "item",
},
visualMap: {
bottom: "bottom",
type: "piecewise",
orient: "horizontal",
min,
max,
text: ["High", "Low"],
calculable: true,
inRange: {
color: ["#e4d8fd", "#c1a4fb", "#b593fa", "#9d70f9"],
},
},
series: [
{
left: 0,
right: 0,
name: "Requests",
type: "map",
roam: true,
map: "world",
label: {
show: true,
formatter: function (d) {
if (!d.data || d.data.value <= labelValue) {
return "";
}
return d.name;
},
},
emphasis: {
label: {
show: true,
},
},
data: requests,
},
],
};
Connected data points
The Business Charts panel can visualize connected data points retrieved from a data source on a GeoJSON map.
let latitudes = [];
let longitude = [];
let values = [];
/**
* Data Source
*/
context.panel.data.series.map((s) => {
latitudes = s.fields.find((f) => f.name === "latitude").values;
longitudes = s.fields.find((f) => f.name === "longitude").values;
values = s.fields.find((f) => f.name === "value").values;
});
/**
* Lines
*/
const lines = longitudes.map((longitude, i) => [longitude, latitudes[i]]);
/**
* Series
*/
const series = latitudes.map((latitude, i) => {
return {
type: "scatter",
coordinateSystem: "geo",
data: [[longitudes[i], latitude, values[i]]],
encode: {
value: 2,
lng: 0,
lat: 1,
},
};
});
/**
* ECharts
*/
return {
geo: {
map: "USA",
roam: true,
itemStyle: {
areaColor: "#e7e8ea",
},
},
tooltip: {},
legend: {},
series: [
...series,
{
name: "Route",
type: "lines",
coordinateSystem: "geo",
geoIndex: 0,
emphasis: {
label: {
show: false,
},
},
lineStyle: {
color: "#c46e54",
width: 5,
opacity: 1,
type: "dotted",
},
data: [
{
coords: lines,
},
],
},
],
};
Dynamic maps loading
You can load additional GeoJSON maps dynamically from data source:
- Set as a String field using Business Input data source.
- Fetched from external URL using Infinity or JSON data sources.
JSON for Canada used in the example can be found here.
const json = context.panel.data.series[0].fields[0].values[0];
/**
* Map Name
*/
const mapName = "Canada";
/**
* Register map
*/
context.echarts.registerMap(mapName, { geoJSON: json });
/**
* Return settiings
*/
return {
title: {
text: mapName,
left: "right",
},
geo: {
map: mapName,
roam: true,
},
};
Switching between maps
The Business Charts panel allows you to switch between GeoJSON maps with on-click or double-click event handlers.
/**
* All countries map
*
* @url https://github.com/codeforgermany/click_that_hood/tree/main/public/data
*/
const allCountriesMap = {
Brazil:
"https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/brazil-states.geojson",
Mexico:
"https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/mexico.geojson",
"United States": "/public/plugins/volkovlabs-echarts-panel/maps/USA.json",
};
/**
* Timeout to process Double Click
*/
let timeFn = null;
/**
* On Mouse Click
*/
context.panel.chart.on("click", (params) => {
clearTimeout(timeFn);
/**
* Time out to allow double click
*/
timeFn = setTimeout(function () {
var name = params.name;
var mapCode = allCountriesMap[name];
/**
* Map is not found in the list
*/
if (!mapCode) {
alert("Not found!");
return;
}
/**
* Register and Load Map
* Resize is required to redraw
*/
if (mapCode) {
return $.get(mapCode, (data) => {
context.echarts.registerMap(name, data);
context.panel.chart.setOption(loadMap(name));
context.panel.chart.resize();
});
}
/**
* Load and redraw World Map
*/
context.panel.chart.setOption(loadMap(name));
context.panel.chart.resize();
}, 250);
});
/**
* On Double click go back to World Map
*/
context.panel.chart.on("dblclick", (params) => {
clearTimeout(timeFn);
context.panel.chart.setOption(loadMap("world"));
context.panel.chart.resize();
});
/**
* Load Map
*
* @returns object for setOption()
*/
const loadMap = (name) => {
return {
title: {
text: "Click to see closer",
subtext: "Double click to go back to World Map",
left: "right",
},
visualMap: {
left: "right",
inRange: {
color: [
"#313695",
"#4575b4",
"#74add1",
"#abd9e9",
"#e0f3f8",
"#ffffbf",
"#fee090",
"#fdae61",
"#f46d43",
"#d73027",
"#a50026",
],
},
text: ["High", "Low"],
calculable: true,
},
geo: {
type: "map",
map: name, // dynamic load map
roam: false,
},
series: [
{
data: [
{ name: "Brazil", value: 100 },
{ name: "United States", value: 100 },
{ name: "Mexico", value: 100 },
],
geoIndex: 0,
type: "map",
},
],
};
};
/**
* Load World Map
*/
return loadMap("world");