Commit 89c8ea79 authored by Rodrigo Tapia-McClung's avatar Rodrigo Tapia-McClung

Update radar chart on date change

parent c88945e4
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
*/ */
/* globals updateBarChart, barChartData, am4charts, am4core, am4themes_animated, yearList */ /* globals updateBarChart, barChartData, am4charts, am4core, am4themes_animated, yearList */
/* export makeRadialChart, makeLineChart, makeAreaChart, makeBarChart */ /* export makeRadarChart, makeLineChart, makeAreaChart, makeBarChart */
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function grijalva_theme(target) { function grijalva_theme(target) {
...@@ -44,29 +44,29 @@ am4core.useTheme(grijalva_theme); ...@@ -44,29 +44,29 @@ am4core.useTheme(grijalva_theme);
let mainTextColor = getComputedStyle(document.body).getPropertyValue('--main-text-color'); let mainTextColor = getComputedStyle(document.body).getPropertyValue('--main-text-color');
const makeRadialSeries = (chart, value, category, name, color) => { const makeRadarSeries = (chart, value, category, name, color) => {
let radialSeries = chart.series.push(new am4charts.RadarSeries()); let radarSeries = chart.series.push(new am4charts.RadarSeries());
radialSeries.dataFields.valueY = value; radarSeries.dataFields.valueY = value;
radialSeries.dataFields.categoryX = category; radarSeries.dataFields.categoryX = category;
radialSeries.strokeWidth = 1.5; radarSeries.strokeWidth = 1.5;
radialSeries.tooltipText = "{valueY}"; radarSeries.tooltipText = "{valueY}";
radialSeries.name = name; radarSeries.name = name;
//radialSeries.connect = false; //radarSeries.connect = false;
//radialSeries.connectEnds = false; //radarSeries.connectEnds = false;
radialSeries.stroke = am4core.color(color); // red radarSeries.stroke = am4core.color(color); // red
radialSeries.tooltip.getFillFromObject = false; radarSeries.tooltip.getFillFromObject = false;
radialSeries.tooltipText = "[bold] {name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]"; radarSeries.tooltipText = "[bold] {name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
radialSeries.tooltip.background.fill = am4core.color(color); radarSeries.tooltip.background.fill = am4core.color(color);
} }
const makeRadialRange = (axis, start, end, color, span) => { const makeRadarRange = (axis, start, end, color, span) => {
let radialRange = axis.axisRanges.create(); let radarRange = axis.axisRanges.create();
radialRange.category = start; radarRange.category = start;
radialRange.endcategory = end; radarRange.endcategory = end;
radialRange.axisFill.fill = am4core.color(color); radarRange.axisFill.fill = am4core.color(color);
radialRange.axisFill.fillOpacity = 0.4; radarRange.axisFill.fillOpacity = 0.4;
radialRange.grid.strokeOpacity = 0; radarRange.grid.strokeOpacity = 0;
radialRange.locations.endCategory = span ? span : ""; radarRange.locations.endCategory = span ? span : "";
} }
const makeLineAxisAndSeries = (chart, field, name, opposite, bullet) => { const makeLineAxisAndSeries = (chart, field, name, opposite, bullet) => {
...@@ -145,64 +145,64 @@ const makeBarSeries = (chart, field, name) => { ...@@ -145,64 +145,64 @@ const makeBarSeries = (chart, field, name) => {
barValueLabel.label.fill = am4core.color("#fff"); barValueLabel.label.fill = am4core.color("#fff");
} }
const makeRadialChart = (data, months, years) => { const makeRadarChart = (data, months, years) => {
let radialChart = am4core.create("radial_chart", am4charts.RadarChart); let radarChart = am4core.create("radial_chart", am4charts.RadarChart);
let radialTitle = radialChart.titles.create(); let radarTitle = radarChart.titles.create();
radialTitle.text = "Superficie total por año"; radarTitle.text = "Superficie total por año";
radialTitle.fontSize = 10; radarTitle.fontSize = 10;
radialTitle.marginBottom = 10; radarTitle.marginBottom = 10;
radialTitle.fill = am4core.color(mainTextColor); radarTitle.fill = am4core.color(mainTextColor);
radialChart.data = data; radarChart.data = data;
/* Create axes */ /* Create axes */
let radialCategoryAxis = radialChart.xAxes.push(new am4charts.CategoryAxis()); let radarCategoryAxis = radarChart.xAxes.push(new am4charts.CategoryAxis());
radialCategoryAxis.dataFields.category = "month"; radarCategoryAxis.dataFields.category = "month";
radialCategoryAxis.fontSize = 9; radarCategoryAxis.fontSize = 9;
radialCategoryAxis.renderer.labels.template.fill = am4core.color(mainTextColor); radarCategoryAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
radialCategoryAxis.renderer.grid.template.stroke = am4core.color(mainTextColor); radarCategoryAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);
let radialValueAxis = radialChart.yAxes.push(new am4charts.ValueAxis()); let radarValueAxis = radarChart.yAxes.push(new am4charts.ValueAxis());
radialValueAxis.renderer.grid.template.stroke = am4core.color(mainTextColor); radarValueAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);
radialValueAxis.extraMin = 0.2; radarValueAxis.extraMin = 0.2;
radialValueAxis.extraMax = 0.2; radarValueAxis.extraMax = 0.2;
radialValueAxis.tooltip.disabled = true; radarValueAxis.tooltip.disabled = true;
radialValueAxis.fontSize = 9; radarValueAxis.fontSize = 9;
radialValueAxis.renderer.labels.template.fill = am4core.color(mainTextColor); radarValueAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
radialValueAxis.renderer.grid.template.stroke = am4core.color(mainTextColor); radarValueAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);
//radialValueAxis.renderer.labels.template.fontSize = 15; //radarValueAxis.renderer.labels.template.fontSize = 15;
/* Create and configure series */ /* Create and configure series */
let seriesColor = ["#F98293", "#2AC2BB", "#FDA259"]; let seriesColor = ["#F98293", "#2AC2BB", "#FDA259"];
years.forEach( (year, i) => { years.forEach( (year, i) => {
makeRadialSeries(radialChart, year, "month", year, seriesColor[i]); makeRadarSeries(radialChart, year, "month", year, seriesColor[i]);
}); });
radialChart.scrollbarX = new am4core.Scrollbar(); radarChart.scrollbarX = new am4core.Scrollbar();
radialChart.scrollbarX.minHeight = 1; radarChart.scrollbarX.minHeight = 1;
radialChart.scrollbarX.parent = radialChart.bottomAxesContainer; radarChart.scrollbarX.parent = radarChart.bottomAxesContainer;
radialChart.scrollbarY = new am4core.Scrollbar(); radarChart.scrollbarY = new am4core.Scrollbar();
radialChart.scrollbarY.minWidth = 1; radarChart.scrollbarY.minWidth = 1;
customizeGrip(radialChart.scrollbarX.startGrip); customizeGrip(radarChart.scrollbarX.startGrip);
customizeGrip(radialChart.scrollbarX.endGrip); customizeGrip(radarChart.scrollbarX.endGrip);
customizeGrip(radialChart.scrollbarY.startGrip); customizeGrip(radarChart.scrollbarY.startGrip);
customizeGrip(radialChart.scrollbarY.endGrip); customizeGrip(radarChart.scrollbarY.endGrip);
let radialRangeColors = ["#E1DBC8", "#595952", "#838278", "#B1AE9F"]; let radarRangeColors = ["#E1DBC8", "#595952", "#838278", "#B1AE9F"];
makeRadialRange(radialCategoryAxis, "enero", "marzo", radialRangeColors[0], 2); makeRadarRange(radarCategoryAxis, "enero", "marzo", radarRangeColors[0], 2);
makeRadialRange(radialCategoryAxis, "marzo", "mayo", radialRangeColors[1], 2); makeRadarRange(radarCategoryAxis, "marzo", "mayo", radarRangeColors[1], 2);
makeRadialRange(radialCategoryAxis, "mayo", "septiembre", radialRangeColors[2], 4); makeRadarRange(radarCategoryAxis, "mayo", "septiembre", radarRangeColors[2], 4);
makeRadialRange(radialCategoryAxis, "septiembre", "diciembre", radialRangeColors[3], 3); makeRadarRange(radarCategoryAxis, "septiembre", "diciembre", radarRangeColors[3], 3);
makeRadialRange(radialCategoryAxis, "diciembre", "diciembre", radialRangeColors[0], 1); makeRadarRange(radarCategoryAxis, "diciembre", "diciembre", radarRangeColors[0], 1);
radialChart.cursor = new am4charts.RadarCursor(); radarChart.cursor = new am4charts.RadarCursor();
// add line legend // add line legend
radialChart.legend = new am4charts.Legend(); radarChart.legend = new am4charts.Legend();
//radialChart.legend.fontSize = 10; //radarChart.legend.fontSize = 10;
radialChart.legend.fontSize = 9; radarChart.legend.fontSize = 9;
radialChart.legend.labels.template.fill = am4core.color(mainTextColor); radarChart.legend.labels.template.fill = am4core.color(mainTextColor);
let legenddata = [{ name: "Estiaje", fill: am4core.color("#595952") }, let legenddata = [{ name: "Estiaje", fill: am4core.color("#595952") },
{ name: "Tropical", fill: am4core.color("#838278") }, { name: "Tropical", fill: am4core.color("#838278") },
...@@ -211,11 +211,11 @@ const makeRadialChart = (data, months, years) => { ...@@ -211,11 +211,11 @@ const makeRadialChart = (data, months, years) => {
]; ];
// add second legend // add second legend
radialChart.legend = new am4charts.Legend(); radarChart.legend = new am4charts.Legend();
radialChart.legend.data = legenddata; radarChart.legend.data = legenddata;
radialChart.legend.fontSize = 10; radarChart.legend.fontSize = 10;
radialChart.legend.labels.template.fill = am4core.color(mainTextColor); radarChart.legend.labels.template.fill = am4core.color(mainTextColor);
let markerTemplate = radialChart.legend.markers.template; let markerTemplate = radarChart.legend.markers.template;
markerTemplate.width = 20; markerTemplate.width = 20;
markerTemplate.height = 20; markerTemplate.height = 20;
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* January 2021 * January 2021
*/ */
/* globals omnivore, Promise, makeBaseMap, am4core, makeRadialChart, makeLineChart, makeAreaChart, makeBarChart */ /* globals omnivore, Promise, makeBaseMap, am4core, makeRadarChart, makeLineChart, makeAreaChart, makeBarChart */
/* exported. userFiles, userDates, timeParse, layerControl, yearList */ /* exported. userFiles, userDates, timeParse, layerControl, yearList */
let timeParse, let timeParse,
...@@ -65,10 +65,11 @@ const sortInitialDateAscending = (a, b) => { ...@@ -65,10 +65,11 @@ const sortInitialDateAscending = (a, b) => {
return a - b; return a - b;
} }
const baseUrl = new URL(`/data`, window.location.href).href;
// query available dates on DB // query available dates on DB
const setupDates = () => { const setupDates = () => {
return new Promise(resolve => { return new Promise(resolve => {
const baseUrl = new URL(`/data`, window.location.href).href;
let layersQuery = `${baseUrl}/list_layers`; let layersQuery = `${baseUrl}/list_layers`;
d3.json(layersQuery).then(layers => { d3.json(layersQuery).then(layers => {
layers.forEach(layer => { layers.forEach(layer => {
...@@ -179,6 +180,7 @@ const populateDates = (dates) => { // fill out date pickers with available dates ...@@ -179,6 +180,7 @@ const populateDates = (dates) => { // fill out date pickers with available dates
} else { } else {
// FIXME: no need to pass data here? // FIXME: no need to pass data here?
updateMap({ map: map, min: startUserDate, max: endUserDate }); updateMap({ map: map, min: startUserDate, max: endUserDate });
updateCharts();
} }
}, },
beforeShow: (el, inst) => { beforeShow: (el, inst) => {
...@@ -317,7 +319,6 @@ const populateMap = async (mapData) => { ...@@ -317,7 +319,6 @@ const populateMap = async (mapData) => {
// after mapboxGL map is ready with styles do this: // after mapboxGL map is ready with styles do this:
glmap.getMapboxMap().on("style.load", () => { glmap.getMapboxMap().on("style.load", () => {
const baseUrl = new URL(`/data`, window.location.href).href;
glmap.getMapboxMap().addSource("basecuerposagua", { glmap.getMapboxMap().addSource("basecuerposagua", {
type: "vector", type: "vector",
//tiles: [`${baseUrl}/basecuerposagua/mvt/{z}/{x}/{y}?geom_column=geom&columns=${indicators.join()},descrip`], //tiles: [`${baseUrl}/basecuerposagua/mvt/{z}/{x}/{y}?geom_column=geom&columns=${indicators.join()},descrip`],
...@@ -426,7 +427,7 @@ const updateMap = (mapData) => { ...@@ -426,7 +427,7 @@ const updateMap = (mapData) => {
// define MVT layer for given month table and all indicators // define MVT layer for given month table and all indicators
const mapboxLayer = (monthYear) => { const mapboxLayer = (monthYear) => {
const baseUrl = new URL(`/data`, window.location.href).href;
let pbfLayer = { let pbfLayer = {
id: monthYear, id: monthYear,
source: { source: {
...@@ -572,19 +573,20 @@ legend.onAdd = () => { ...@@ -572,19 +573,20 @@ legend.onAdd = () => {
return div; return div;
}; };
let barChartData = [], let radarData = [],
barChartData = [],
yearList; yearList;
const makeCharts = () => { const makeCharts = () => {
let baseUrl = new URL(`/data`, window.location.href).href;
// create sets of unique months and years // create sets of unique months and years
yearList = [... new Set(userDates.map( date => new Date(date).getFullYear() ))]; yearList = [... new Set(userDates.map( date => new Date(date).getFullYear() ))];
let allYears = [... new Set(dateArray.map( date => new Date(date).getFullYear() ))];
//let formatter = new Intl.DateTimeFormat('es', { month: 'long' }); //let formatter = new Intl.DateTimeFormat('es', { month: 'long' });
// RADIAL CHART // RADAR CHART
// get am chart - may need this to update chart on date change // get am chart - may need this to update chart on date change
//let radialChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "radial_chart"); //let radarChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "radial_chart");
// async queries for each date that has been loaded // async queries for each date that has been loaded
const queries = userFiles.map(async (mes, i) => { const queries = userFiles.map(async (mes, i) => {
...@@ -592,25 +594,26 @@ const makeCharts = () => { ...@@ -592,25 +594,26 @@ const makeCharts = () => {
let query = `${baseUrl}/query/${mes}?columns=sum(areacpo)/10000 area`; let query = `${baseUrl}/query/${mes}?columns=sum(areacpo)/10000 area`;
const queryData = await d3.json(query); const queryData = await d3.json(query);
queryData[0].date = new Date(userDates[i]); queryData[0].date = new Date(userDates[i]);
radarData.push(queryData[0]);
return new Promise(resolve => { return new Promise(resolve => {
resolve(queryData[0]); resolve(queryData[0]);
}); });
}); });
// wait for all queries to complete and then set chart data // wait for all queries to complete and then set chart data
Promise.all(queries).then( data => { Promise.all(queries).then( data => {
radarData.sort((a, b) => (a.date > b.date) ? 1 : -1);
// TODO: maybe make this a function so it can be used to update chart when changing dates // TODO: maybe make this a function so it can be used to update chart when changing dates
let radialChartData = []; let radarChartData = [];
monthArray.forEach( (month, index) => { monthArray.forEach( (month, index) => {
let element = {}; let element = {};
yearList.forEach( year => { yearList.forEach( year => {
//element.month = formatter.format(new Date(year, month, 1, 0, 0, 0));
element.month = month.toLowerCase(); element.month = month.toLowerCase();
let yearData = data.filter(d => new Date(d.date).getMonth() == index && new Date(d.date).getFullYear() == year); 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; element[year] = yearData.length > 0 ? yearData[0].area : null;
}); });
radialChartData.push(element); radarChartData.push(element);
}); });
makeRadialChart(radialChartData, monthArray, yearList); makeRadarChart(radarChartData, monthArray, allYears);
}); });
// LINE + STACKED AREA CHARTS // LINE + STACKED AREA CHARTS
...@@ -707,3 +710,49 @@ const updateBarChart = (filterDate, data) => { ...@@ -707,3 +710,49 @@ const updateBarChart = (filterDate, data) => {
popBarsChart.invalidateRawData(); popBarsChart.invalidateRawData();
} }
} }
const updateCharts = () => {
yearList = [... new Set(userDates.map( date => new Date(date).getFullYear() ))];
// update radar chart
let radarChart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "radial_chart");
const queries = userDates.map( async (date, i) => {
let checkDate = new Date(date);
// check what month has not been queried before and query it
if (!radarData.some(d => d.date.valueOf() === checkDate.valueOf())) {
let query = `${baseUrl}/query/${userFiles[i]}?columns=sum(areacpo)/10000 area`;
const queryData = await d3.json(query);
queryData[0].date = new Date(userDates[i]);
radarData.push(queryData[0]);
return new Promise(resolve => {
resolve(queryData[0]);
});
}
})
// wait for all queries to complete and then set chart data
Promise.all(queries).then( () => {
// TODO: maybe make this a function so it can be used to update chart when changing dates
let radarChartData = [];
// check what months should have data
radarData.sort((a, b) => (a.date > b.date) ? 1 : -1);
let booleanCheck = radarData.map( (d,i) => d.date.valueOf() == userDates[i]);
let newRadarData = radarData.map( (d,i) => {
if (booleanCheck[i]) return d;
});
let filtredRadarData = newRadarData.filter( d => d != undefined );
monthArray.forEach( (month, index) => {
let element = {};
yearList.forEach( year => {
element.month = month.toLowerCase();
let yearData = filtredRadarData.filter(d => new Date(d.date).getMonth() == index && new Date(d.date).getFullYear() == year);
element[year] = yearData.length > 0 ? yearData[0].area : null;
});
radarChartData.push(element);
});
radarChart.data = radarChartData;
radarChart.invalidateRawData();
});
}
\ No newline at end of file
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