Commit 25d53dee authored by Rodrigo Tapia-McClung's avatar Rodrigo Tapia-McClung

Improve line chart creation

parent 4b3219fd
......@@ -5,8 +5,8 @@
* January 2021
*/
/* globals updateBarChart, barChartData, am4charts, am4core, am4themes_animated */
/* export makeRadialChart */
/* globals updateBarChart, barChartData, am4charts, am4core, am4themes_animated, yearList */
/* export makeRadialChart, makeLineChart */
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function grijalva_theme(target) {
......@@ -27,7 +27,7 @@ function customizeGrip(grip) {
grip.background.disabled = true;
// Add rotated rectangle as bi-di arrow
var img = grip.createChild(am4core.Rectangle);
let img = grip.createChild(am4core.Rectangle);
img.width = 7;
img.height = 7;
img.fill = am4core.color("#999");
......@@ -39,8 +39,69 @@ function customizeGrip(grip) {
let mainTextColor = getComputedStyle(document.body).getPropertyValue('--main-text-color');
const createRadialSeries = (chart, value, category, name, color) => {
let radialSeries = chart.series.push(new am4charts.RadarSeries());
radialSeries.dataFields.valueY = value;
radialSeries.dataFields.categoryX = category;
radialSeries.strokeWidth = 1.5;
radialSeries.tooltipText = "{valueY}";
radialSeries.name = name;
//radialSeries.connect = false;
//radialSeries.connectEnds = false;
radialSeries.stroke = am4core.color(color); // red
radialSeries.tooltip.getFillFromObject = false;
radialSeries.tooltipText = "[bold] {name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
radialSeries.tooltip.background.fill = am4core.color(color);
}
const makeRadialRange = (axis, start, end, color, span) => {
let radialRange = axis.axisRanges.create();
radialRange.category = start;
radialRange.endcategory = end;
radialRange.axisFill.fill = am4core.color(color);
radialRange.axisFill.fillOpacity = 0.4;
radialRange.grid.strokeOpacity = 0;
radialRange.locations.endCategory = span ? span : "";
}
const createLineAxisAndSeries = (chart, field, name, opposite, bullet) => {
var lineValueAxis = chart.yAxes.push(new am4charts.ValueAxis());
lineValueAxis.fontSize = 8;
if (chart.yAxes.indexOf(lineValueAxis) != 0) {
lineValueAxis.syncWithAxis = chart.yAxes.getIndex(0);
}
var lineSeries = chart.series.push(new am4charts.LineSeries());
lineSeries.dataFields.valueY = field;
lineSeries.dataFields.dateX = "date";
lineSeries.strokeWidth = 2;
lineSeries.yAxis = lineValueAxis;
lineSeries.name = name;
//series.tooltipText = "{name}: [bold]{valueY.formatNumber('#,###.0')} Ha[/]";
lineSeries.tooltipText = "[bold]{name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
lineSeries.tooltipText.fontSize = 8;
lineSeries.tensionX = 0.8;
lineSeries.showOnInit = true;
lineValueAxis.renderer.line.strokeOpacity = 1;
lineValueAxis.renderer.line.strokeWidth = 2;
lineValueAxis.renderer.line.stroke = lineSeries.stroke;
lineValueAxis.renderer.labels.template.fill = lineSeries.stroke;
lineValueAxis.renderer.opposite = opposite;
}
const makeLineRange = (axis, start, width, color) => {
yearList.forEach( y => {
var range = axis.axisRanges.create();
range.date = new Date(y, start, 1, 0, 0, 0);
range.endDate = new Date(y, start+width, 1, 0, 0, 0);
range.axisFill.fill = am4core.color(color);
range.axisFill.fillOpacity = 0.4;
})
}
const makeRadialChart = (data, months, years) => {
var radialChart = am4core.create("radial_chart", am4charts.RadarChart);
let radialChart = am4core.create("radial_chart", am4charts.RadarChart);
let radialTitle = radialChart.titles.create();
radialTitle.text = "Superficie total por año";
......@@ -51,14 +112,13 @@ const makeRadialChart = (data, months, years) => {
radialChart.data = data;
/* Create axes */
let radialCategoryAxis = radialChart.xAxes.push(new am4charts.CategoryAxis());
radialCategoryAxis.dataFields.category = "month";
radialCategoryAxis.fontSize = 9;
radialCategoryAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
radialCategoryAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);
var radialValueAxis = radialChart.yAxes.push(new am4charts.ValueAxis());
let radialValueAxis = radialChart.yAxes.push(new am4charts.ValueAxis());
radialValueAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);
radialValueAxis.extraMin = 0.2;
radialValueAxis.extraMax = 0.2;
......@@ -69,19 +129,6 @@ const makeRadialChart = (data, months, years) => {
//radialValueAxis.renderer.labels.template.fontSize = 15;
/* Create and configure series */
const createRadialSeries = (chart, value, category, name, color) => {
let radialSeries = chart.series.push(new am4charts.RadarSeries());
radialSeries.dataFields.valueY = value;
radialSeries.dataFields.categoryX = category;
radialSeries.strokeWidth = 1.5;
radialSeries.tooltipText = "{valueY}";
radialSeries.name = name
radialSeries.stroke = am4core.color(color); // red
radialSeries.tooltip.getFillFromObject = false;
radialSeries.tooltipText = "[bold] {name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
radialSeries.tooltip.background.fill = am4core.color(color);
}
let seriesColor = ["#F98293", "#2AC2BB", "#FDA259"];
years.forEach( (year, i) => {
createRadialSeries(radialChart, year, "month", year, seriesColor[i]);
......@@ -97,22 +144,12 @@ const makeRadialChart = (data, months, years) => {
customizeGrip(radialChart.scrollbarY.startGrip);
customizeGrip(radialChart.scrollbarY.endGrip);
const makeRadialRange = (start, end, color, span) => {
let radialRange = radialCategoryAxis.axisRanges.create();
radialRange.category = start;
radialRange.endcategory = end;
radialRange.axisFill.fill = am4core.color(color);
radialRange.axisFill.fillOpacity = 0.4;
radialRange.grid.strokeOpacity = 0;
radialRange.locations.endCategory = span ? span : "";
}
let radialRangeColors = ["#E1DBC8", "#595952", "#838278", "#B1AE9F"];
makeRadialRange("enero", "marzo", radialRangeColors[0], 2);
makeRadialRange("marzo", "mayo", radialRangeColors[1], 2);
makeRadialRange("mayo", "septiembre", radialRangeColors[2], 4);
makeRadialRange("septiembre", "diciembre", radialRangeColors[3], 3);
makeRadialRange("diciembre", "diciembre", radialRangeColors[0], 1);
makeRadialRange(radialCategoryAxis, "enero", "marzo", radialRangeColors[0], 2);
makeRadialRange(radialCategoryAxis, "marzo", "mayo", radialRangeColors[1], 2);
makeRadialRange(radialCategoryAxis, "mayo", "septiembre", radialRangeColors[2], 4);
makeRadialRange(radialCategoryAxis, "septiembre", "diciembre", radialRangeColors[3], 3);
makeRadialRange(radialCategoryAxis, "diciembre", "diciembre", radialRangeColors[0], 1);
radialChart.cursor = new am4charts.RadarCursor();
......@@ -121,7 +158,7 @@ const makeRadialChart = (data, months, years) => {
radialChart.legend.fontSize = 9;
radialChart.legend.labels.template.fill = am4core.color(mainTextColor);
var legenddata = [{ name: "Estiaje", fill: am4core.color("#595952") },
let legenddata = [{ name: "Estiaje", fill: am4core.color("#595952") },
{ name: "Tropical", fill: am4core.color("#838278") },
{ name: "Tropical-Invernal", fill: am4core.color("#B1AE9F") },
{ name: "Invernal", fill: am4core.color("#E1DBC8") }
......@@ -130,70 +167,38 @@ const makeRadialChart = (data, months, years) => {
radialChart.legend.data = legenddata;
radialChart.legend.fontSize = 10;
radialChart.legend.labels.template.fill = am4core.color(mainTextColor);
var markerTemplate = radialChart.legend.markers.template;
let markerTemplate = radialChart.legend.markers.template;
markerTemplate.width = 20;
markerTemplate.height = 20;
}
am4core.ready(function() {
// Themes begin
am4core.useTheme(am4themes_animated);
am4core.useTheme(grijalva_theme);
//let mainTextColor = getComputedStyle(document.body).getPropertyValue('--main-text-color');
// Themes end
const makeLineChart = (data) => {
// linea chart
let lineChart = am4core.create("linesChart", am4charts.XYChart);
let lineTitle = lineChart.titles.create();
lineTitle.text = "Superficie por tipo de cuerpo";
lineTitle.fontSize = 10;
lineTitle.marginBottom = 15;
lineTitle.fill = am4core.color(mainTextColor);
// Increase contrast by taking evey second color
//chart.colors.step = 2;
lineChart.data = data;
// Add data
lineChart.data = generateChartData();
// Create axes
var lineDateAxis = lineChart.xAxes.push(new am4charts.DateAxis());
lineDateAxis.renderer.minGridDistance = 50;
lineDateAxis.fontSize = 8;
lineDateAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
// Create series
function createAxisAndSeries(field, name, opposite, bullet) {
var lineValueAxis = lineChart.yAxes.push(new am4charts.ValueAxis());
lineValueAxis.fontSize = 8;
createLineAxisAndSeries(lineChart, "permanente", "Agua permanente", false, "circle");
createLineAxisAndSeries(lineChart, "temporal", "Áreas temporalmente inundadas", true, "triangle");
createLineAxisAndSeries(lineChart, "vegetacion", "Suelos húmedos-vegetación acuática", true, "rectangle");
if (lineChart.yAxes.indexOf(lineValueAxis) != 0) {
lineValueAxis.syncWithAxis = lineChart.yAxes.getIndex(0);
}
var lineSeries = lineChart.series.push(new am4charts.LineSeries());
lineSeries.dataFields.valueY = field;
lineSeries.dataFields.dateX = "date";
lineSeries.strokeWidth = 2;
lineSeries.yAxis = lineValueAxis;
lineSeries.name = name;
//series.tooltipText = "{name}: [bold]{valueY.formatNumber('#,###.0')} Ha[/]";
lineSeries.tooltipText = "[bold]{name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
lineSeries.tooltipText.fontSize = 8;
lineSeries.tensionX = 0.8;
lineSeries.showOnInit = true;
lineValueAxis.renderer.line.strokeOpacity = 1;
lineValueAxis.renderer.line.strokeWidth = 2;
lineValueAxis.renderer.line.stroke = lineSeries.stroke;
lineValueAxis.renderer.labels.template.fill = lineSeries.stroke;
lineValueAxis.renderer.opposite = opposite;
}
createAxisAndSeries("permanente", "Agua permanente", false, "circle");
createAxisAndSeries("temporal", "Áreas temporalmente inundadas", true, "triangle");
createAxisAndSeries("vegetacion", "Suelos húmedos-vegetación acuática", true, "rectangle");
// create line ranges
makeLineRange(lineDateAxis, 0, 2, "#E1DBC8");
makeLineRange(lineDateAxis, 2, 2, "#595952");
makeLineRange(lineDateAxis, 4, 4, "#838278");
makeLineRange(lineDateAxis, 8, 3, "#B1AE9F");
makeLineRange(lineDateAxis, 11, 1, "#E1DBC8");
// Add cursor
lineChart.cursor = new am4charts.XYCursor();
......@@ -203,96 +208,15 @@ am4core.ready(function() {
customizeGrip(lineChart.scrollbarX.startGrip);
customizeGrip(lineChart.scrollbarX.endGrip);
// Style scrollbar
}
// generate some random data, quite different range
function generateChartData() {
var chartData = [];
var firstDate = new Date();
firstDate.setDate(firstDate.getDate() - 100);
firstDate.setHours(0, 0, 0, 0);
return chartData;
}
am4core.ready(function() {
// axis ranges
//TODO: make these ranges in a more efficient way
var lineRange = lineDateAxis.axisRanges.create();
lineRange.date = new Date(2016, 0, 1);
lineRange.endDate = new Date(2016, 2, 1);
lineRange.axisFill.fill = am4core.color("#E1DBC8");
lineRange.axisFill.fillOpacity = 0.4;
var lineRange1 = lineDateAxis.axisRanges.create();
lineRange1.date = new Date(2016, 2, 1);
lineRange1.endDate = new Date(2016, 4, 1);
lineRange1.axisFill.fill = am4core.color("#595952");
lineRange1.axisFill.fillOpacity = 0.4;
var lineRange2 = lineDateAxis.axisRanges.create();
lineRange2.date = new Date(2016, 4, 1);
lineRange2.endDate = new Date(2016, 8, 1);
lineRange2.axisFill.fill = am4core.color("#838278");
lineRange2.axisFill.fillOpacity = 0.4;
var lineRange3 = lineDateAxis.axisRanges.create();
lineRange3.date = new Date(2016, 8, 1);
lineRange3.endDate = new Date(2016, 11, 1);
lineRange3.axisFill.fill = am4core.color("#B1AE9F");
lineRange3.axisFill.fillOpacity = 0.4;
var lineRange4 = lineDateAxis.axisRanges.create();
lineRange4.date = new Date(2016, 11, 1);
lineRange4.endDate = new Date(2017, 2, 1);
lineRange4.axisFill.fill = am4core.color("#E1DBC8");
lineRange4.axisFill.fillOpacity = 0.4;
var lineRange5 = lineDateAxis.axisRanges.create();
lineRange5.date = new Date(2017, 2, 1);
lineRange5.endDate = new Date(2017, 4, 1);
lineRange5.axisFill.fill = am4core.color("#595952");
lineRange5.axisFill.fillOpacity = 0.4;
var lineRange6 = lineDateAxis.axisRanges.create();
lineRange6.date = new Date(2017, 4, 1);
lineRange6.endDate = new Date(2017, 8, 1);
lineRange6.axisFill.fill = am4core.color("#838278");
lineRange6.axisFill.fillOpacity = 0.4;
var lineRange7 = lineDateAxis.axisRanges.create();
lineRange7.date = new Date(2017, 8, 1);
lineRange7.endDate = new Date(2017, 11, 1);
lineRange7.axisFill.fill = am4core.color("#B1AE9F");
lineRange7.axisFill.fillOpacity = 0.4;
var lineRange8 = lineDateAxis.axisRanges.create();
lineRange8.date = new Date(2017, 11, 1);
lineRange8.endDate = new Date(2018, 2, 1);
lineRange8.axisFill.fill = am4core.color("#E1DBC8");
lineRange8.axisFill.fillOpacity = 0.4;
var lineRange9 = lineDateAxis.axisRanges.create();
lineRange9.date = new Date(2018, 2, 1);
lineRange9.endDate = new Date(2018, 4, 1);
lineRange9.axisFill.fill = am4core.color("#595952");
lineRange9.axisFill.fillOpacity = 0.4;
var lineRange10 = lineDateAxis.axisRanges.create();
lineRange10.date = new Date(2018, 4, 1);
lineRange10.endDate = new Date(2018, 8, 1);
lineRange10.axisFill.fill = am4core.color("#838278");
lineRange10.axisFill.fillOpacity = 0.4;
var lineRange11 = lineDateAxis.axisRanges.create();
lineRange11.date = new Date(2018, 8, 1);
lineRange11.endDate = new Date(2018, 11, 1);
lineRange11.axisFill.fill = am4core.color("#B1AE9F");
lineRange11.axisFill.fillOpacity = 0.4;
var lineRange12 = lineDateAxis.axisRanges.create();
lineRange12.date = new Date(2018, 11, 1);
lineRange12.endDate = new Date(2019, 0, 1);
lineRange12.axisFill.fill = am4core.color("#E1DBC8");
lineRange12.axisFill.fillOpacity = 0.4;
// Themes begin
am4core.useTheme(am4themes_animated);
am4core.useTheme(grijalva_theme);
//let mainTextColor = getComputedStyle(document.body).getPropertyValue('--main-text-color');
// Themes end
// area chart
let areaChart = am4core.create("stackedAreaChart", am4charts.XYChart);
......
......@@ -5,7 +5,7 @@
* January 2021
*/
/* globals omnivore, Promise, makeBaseMap, am4core, makeRadialChart */
/* globals omnivore, Promise, makeBaseMap, am4core, makeRadialChart, makeLineChart */
/* exported. userFiles, userDates, timeParse, layerControl, yearList */
let timeParse,
......@@ -288,6 +288,10 @@ let barChartData = [],
const populateMap = async(mapData) => {
let baseUrl = new URL(`/data`, window.location.href).href;
// create sets of unique months and years
yearList = [... new Set(userDates.map( date => new Date(date).getFullYear() ))];
//let formatter = new Intl.DateTimeFormat('es', { month: 'long' });
// RADIAL CHART
// get am chart - may need this to update chart on date change
//let radialChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "radial_chart");
......@@ -297,20 +301,15 @@ const populateMap = async(mapData) => {
//let query = `${baseUrl}/query/${mes}?columns=sum(areacpo)/10000 value1,sum(perimcpo) value2, sum(dimfrcpo) value3`;
let query = `${baseUrl}/query/${mes}?columns=sum(areacpo)/10000 area`;
const queryData = await d3.json(query);
queryData[0].date = new Date(userDates[i])
queryData[0].date = new Date(userDates[i]);
return new Promise(resolve => {
resolve(queryData[0]);
});
});
// wait for all queries to complete and then set chart data
Promise.all(queries).then( data => {
// create sets of unique months and years
yearList = [... new Set(userDates.map( date => new Date(date).getFullYear() ))];
//let formatter = new Intl.DateTimeFormat('es', { month: 'long' });
// TODO: maybe make this a function so it can be used to update chart when changing dates
let chartaData = [];
let chartData = [];
monthArray.forEach( (month, index) => {
let element = {};
yearList.forEach( year => {
......@@ -319,51 +318,49 @@ const populateMap = async(mapData) => {
let yearData = data.filter(d => new Date(d.date).getMonth() == index && new Date(d.date).getFullYear() == year);
element[year] = yearData.length > 0 ? yearData[0].area : null;
});
chartaData.push(element);
chartData.push(element);
});
makeRadialChart(chartaData, monthArray, yearList);
makeRadialChart(chartData, monthArray, yearList);
});
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LINE CHART
let data_ls = [];
let linesChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "linesChart");
//LINE CHART
// get am chart - may need this to update chart on date change
//let linesChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "linesChart");
// async queries for each date that has been loaded
const queries_ls = userFiles.map(async(mes, i) => {
let query = `${baseUrl}/query/${mes}?columns=sum(areacpo)/10000 area, descrip&group=descrip`;
const queryData = await d3.json(query);
let date = new Date(dateArray[i]);
//date.setFullYear(2016)
for (const wbody in queryData) {
queryData[wbody].date = date;
queryData[wbody].date = new Date(userDates[i]);
}
data_ls.push(queryData);
return new Promise(resolve => {
resolve(queryData);
});
});
// wait for all queries to complete
const dataQueries_ls = await Promise.all(queries_ls);
// and then set chart data
//lineStackedChart.data = data_ls;
var merged = [].concat.apply([], data_ls);
//console.log(merged);
let aguaPermanente = merged.filter(function(d) { return d.descrip == "Agua permanente" });
let aguaTemporal = merged.filter(function(d) { return d.descrip == "Áreas temporalmente inundadas" });
let aguaVegetacion = merged.filter(function(d) { return d.descrip == "Suelos húmedos-vegetación acuática" });
let i;
for (i = 0; i < aguaPermanente.length; i++) {
aguaPermanente[i].permanente = aguaPermanente[i].area;
aguaPermanente[i].temporal = aguaTemporal[i].area;
aguaPermanente[i].vegetacion = aguaVegetacion[i].area;
delete aguaPermanente[i].descrip;
delete aguaPermanente[i].area;
}
// wait for all queries to complete and then set chart data
Promise.all(queries_ls).then( data => {
// TODO: maybe make this a function so it can be used to update chart when changing dates
let merged = [].concat.apply([], data);
let aguaPermanente = merged.filter(d => d.descrip == "Agua permanente" );
let aguaTemporal = merged.filter(d => d.descrip == "Áreas temporalmente inundadas" );
let aguaVegetacion = merged.filter(d => d.descrip == "Suelos húmedos-vegetación acuática" );
let chartData = [];
aguaPermanente.forEach( (wb, i) => {
let element = {
permanente: aguaPermanente[i].area,
temporal: aguaTemporal[i].area,
vegetacion: aguaVegetacion[i].area,
date: aguaPermanente[i].date
}
chartData.push(element);
});
let grijalva_bodies = aguaPermanente;
grijalva_bodies.sort((a, b) => (a.date > b.date) ? 1 : -1);
linesChart.data = grijalva_bodies;
chartData.sort((a, b) => (a.date > b.date) ? 1 : -1);
makeLineChart(chartData);
});
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STACKED AREAS CHART
let data_sa = [];
let stackedAreaChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "stackedAreaChart");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment