Quick start
The example below, running in the Mappia calculator - click it to run it live. Full-size picture
- Run it
Click the picture: the map opens right here and runs the example. Nothing is saved, and nothing to install.
- Try it
- Look at the layer panel: a pie chart shows the area of each geological era.
- Hover a slice: the tooltip shows that era’s share of the total area, in percent.
- Make it yours
Copy the query, change it - the key parameters are below - and run it again in the playground, or paste it into the Mappia editor to save it as your map.
- More ways to use it
Key parameters
| Parameter | Example | What it does |
|---|---|---|
chart | Highcharts.chart("era_chart", { chart: { type: "pie" }, series: [{ data: data }] }) | Draws a chart into the element with that id. Declare the element in descriptionHtml first. |
getHighchartById | ExtjsUtils.HIGHCHART.getById("era_chart") | Returns the chart already drawn in that element, or null. Update or destroy it before drawing again. |
loadScriptOnce | AsyncLoader.loadScriptOnce("/theme/app/js/highcharts/latest/sankey.js", drawSankey) | Loads an extra Highcharts module once, then calls your function. Needed for Sankey diagrams. |
Every parameter, with its type and default, is in the reference at the end of this page.
Complete example
The query 33 lines · runs as is
// Charts: Highcharts is loaded on the map pages. Put a container in the panel, draw in
// afterCalc (the panel exists by then), and replace the chart on the next round.
[
{
title: "Geology - share by era",
name: "CSR:geologia",
source: "calculate",
opacity: 0.8,
visibility: true,
paramsButtonConfig: [{ type: "query", pressed: true }],
descriptionHtml:
"{{loadjson|id=areas|url=/theme/app/data/geologia_area.json}}" +
'<div id="era_chart" style="width:290px;height:240px"></div>',
// afterCalc runs once the expression's values are computed, so the layer needs one
expression: function (layersVals) {
return layersVals[0];
},
afterCalc: function (inputs) {
var areas = inputs.id["areas"];
var data = Object.keys(areas).map(function (era) { return { name: era, y: areas[era] }; });
var old = ExtjsUtils.HIGHCHART.getById("era_chart");
if (old) old.destroy();
Highcharts.chart("era_chart", {
chart: { type: "pie" },
title: { text: "Area by geological era" },
credits: { enabled: false },
tooltip: { pointFormat: "{point.percentage:.1f}%" },
plotOptions: { pie: { dataLabels: { enabled: false } } },
series: [{ name: "Area", data: data }],
});
},
},
];More examples
Other ways to use Charts, each a complete query that runs as is - like the one above.
A line chart from a CSV file
Loadcsv reads a table published next to the map, and afterCalc draws it in the panel - the CO2 emitted for each share of the forest cleared.
Click the picture to run it live. Full-size picture
The query 41 lines · runs as is
// A line chart from a CSV file: loadcsv reads a table published next to the map, and afterCalc draws it in the panel - the CO2 emitted for each share of the forest cleared.
// The input holds a CsvTable: getLineCount() and getValue(column, line), columns by position.
// afterCalc runs once the expression's values are computed, so the layer needs one.
[
{
title: "Carbon stock, and the cost of clearing it",
name: "CSR:biomassa_inv_br_redd",
source: "calculate",
opacity: 0.8,
visibility: true,
paramsButtonConfig: [{ type: "query", pressed: true }],
descriptionHtml:
"{{loadcsv|id=emissions|url=/theme/app/data/emissoesco2.csv}}" +
'<div id="emissions_chart" style="width:290px;height:220px"></div>',
expression: function (layersVals) {
return layersVals[0];
},
afterCalc: function (inputs) {
var table = inputs.id["emissions"];
var points = [];
for (var line = 0; line < table.getLineCount(); line++) {
// column 0: share of the forest cleared (%); column 1: CO2 emitted (tonnes)
var cleared = parseFloat(table.getValue(0, line));
var emitted = parseFloat(table.getValue(1, line));
if (isNaN(cleared) || isNaN(emitted)) continue; // e.g. the empty line a file ends with
points.push([cleared, emitted / 1e9]);
}
var old = ExtjsUtils.HIGHCHART.getById("emissions_chart");
if (old) old.destroy();
Highcharts.chart("emissions_chart", {
chart: { type: "line" },
title: { text: "CO2 emitted by clearing the forest" },
credits: { enabled: false },
legend: { enabled: false },
xAxis: { title: { text: "Forest cleared (%)" } },
yAxis: { title: { text: "Billion tonnes of CO2" } },
series: [{ name: "CO2 emitted", data: points }],
});
},
},
];Customize it
Where to draw
Highcharts is already loaded on the map pages. Put a container with a fixed size in descriptionHtml (the layer panel is about 300 pixels wide), then draw from a callback, once the panel exists: afterCalc, beforeCalc, onInputsReady or a button handler. Never draw inside expression: it runs in a worker, where there is no page.
afterCalc runs only for a layer that has an expression. That is why the example has one, even though it only returns the map’s own value (return layersVals[0]).
Update instead of starting over
afterCalc runs after every calculation round, so a chart drawn there must deal with the previous one. Either destroy it, as the example does, or keep it and swap the data:
var chart = ExtjsUtils.HIGHCHART.getById("era_chart");
if (chart) {
chart.series[0].setData(data); // same chart, new values
} else {
Highcharts.chart("era_chart", { chart: { type: "pie" }, series: [{ name: "Area", data: data }] });
}
Data for the chart
The example reads its numbers from a JSON file loaded with {{loadjson}}; a CSV works the same way with {{loadcsv}}. To reuse the map’s colors, read this.getLegendEntries(): each entry has color ([R, G, B]), title and isNull. It has no counts or areas, so the numbers must come from your data.
Sankey diagrams
A Sankey (flows between categories, such as land-use transitions) needs its module first. Each data row is one transition, [from, to, weight]:
AsyncLoader.loadScriptOnce("/theme/app/js/highcharts/latest/sankey.js", function () {
Highcharts.chart("transitions_chart", {
title: { text: "Land use transitions" },
series: [{ type: "sankey", keys: ["from", "to", "weight"],
data: [["Forest", "Pasture", 120], ["Pasture", "Crop", 45]] }],
});
});
Pitfalls
- Ids are page-wide: two layers cannot use the same container id.
- A chart too large for the panel fits well in a Window.
- The standard chart types are built in. Other Highcharts modules, like Sankey, must be loaded with
AsyncLoader.loadScriptOncebefore you draw.