Commit bdb7e537 authored by Rodrigo Tapia-McClung's avatar Rodrigo Tapia-McClung

Updateable OD matrix amchart w/ gradient heatLegend

parent 3172bb29
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Crecimiento urbano en la regi&oacute;n metropolitana centro pa&iacute</title> <title>Crecimiento urbano en la regi&oacute;n metropolitana centro pa&iacute;s</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" /> <link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" /> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" />
...@@ -76,8 +76,8 @@ ...@@ -76,8 +76,8 @@
<div class="loader"></div> <div class="loader"></div>
<div class="row h-50 border-bottom"> <div class="row h-50 border-bottom">
<div class="col-6 border-right"> <div class="col-6 border-right">
<div id="area-graph"> <div id="tablediv">
<table class="table table-dark table-striped" id="tblViajesDesde"> <table class="table table-dark table-striped" id="tblViajes">
<thead> <thead>
<tr> <tr>
<th scope="col">Origen</th> <th scope="col">Origen</th>
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
</div> </div>
<div class="row h-50"> <div class="row h-50">
<div class="col-6 border-right"> <div class="col-6 border-right">
<div id="costa-graph"></div> <div id="amchartdiv"></div>
</div> </div>
<div class="col-6"> <div class="col-6">
<div id="df-graph"></div> <div id="df-graph"></div>
...@@ -163,9 +163,15 @@ ...@@ -163,9 +163,15 @@
<!-- load animation tweening lib requirement for CanvasFlowMapLayer --> <!-- load animation tweening lib requirement for CanvasFlowMapLayer -->
<script src="https://unpkg.com/@tweenjs/tween.js@18.5/dist/tween.umd.js"></script> <script src="https://unpkg.com/@tweenjs/tween.js@18.5/dist/tween.umd.js"></script>
<script src="../js/CanvasFlowmapLayer.js"></script> <script src="../js/CanvasFlowmapLayer.js"></script>
<!-- amcharts-->
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<script src="../js/centropais_functions.js"></script> <script src="../js/centropais_functions.js"></script>
<script src="../js/centropais_basemap.js"></script> <script src="../js/centropais_basemap.js"></script>
<!--<script src="../js/grijalva_charts.js"></script>--> <script src="../js/centropais_charts.js"></script>
</body> </body>
......
:root { :root {
--main-bg-color: #262626; --main-bg-color:#262626;
--main-text-color: #b2b2b2; --main-text-color:#b2b2b2;
--cell-bg-color:#333;
} }
*{ *{
...@@ -15,6 +16,10 @@ body { ...@@ -15,6 +16,10 @@ body {
color:#333; color:#333;
font-family:sans-serif; font-family:sans-serif;
background-color: var(--main-bg-color); background-color: var(--main-bg-color);
/*line-height: 1.5;
font: 12px sans-serif;
/*color: var(--main-text-color);
background-color: var(--cell-bg-color);*/
} }
.img_bg{ .img_bg{
...@@ -237,6 +242,10 @@ span.frac > span { ...@@ -237,6 +242,10 @@ span.frac > span {
display: none; display: none;
} }
#tblViajes {
font: 12px sans-serif;
}
/****** /******
Icons Icons
******/ ******/
...@@ -328,7 +337,7 @@ Icons ...@@ -328,7 +337,7 @@ Icons
[class^="fa-"], [class*=" fa-"] { [class^="fa-"], [class*=" fa-"] {
/* use !important to prevent issues with browser extensions that change fonts */ /* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important; font-family: 'icomoon' /*!important*/;
speak: none; speak: none;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
...@@ -428,6 +437,16 @@ Icons ...@@ -428,6 +437,16 @@ Icons
} }
/* Graphs */ /* Graphs */
#amchartdiv {
width: 100%;
height: 100%;
}
.amcharttooltip {
font: 12px sans-serif;
}
.active { .active {
text-decoration: underline; text-decoration: underline;
font-weight: 600; font-weight: 600;
...@@ -482,7 +501,7 @@ Icons ...@@ -482,7 +501,7 @@ Icons
.tooltip { .tooltip {
position: absolute; position: absolute;
bottom: 50%; /* so it is not added below the map and scroll bars appear */ /*bottom: 50%; /* so it is not added below the map and scroll bars appear */
/*width: 120px; /*width: 120px;
height: 20px;*/ height: 20px;*/
z-index: 1001; z-index: 1001;
......
/* /*
* Copyright 2019 - All rights reserved. * Copyright 2019-2020 - All rights reserved.
* Rodrigo Tapia-McClung * Rodrigo Tapia-McClung
* *
* August-September 2019 * August 2019 - June 2020
*/ */
/* global baseFileSize, formatBytes, Promise, omnivore, JSZip, map, layerControl, intervals, updateCharts, odClick*/ /* global baseFileSize, formatBytes, Promise, omnivore, JSZip, map, layerControl, intervals, updateCharts, odClick, am4core*/
/* exported makeBaseMap, baseLayerPromises, drawnItems */ /* exported, odData, makeBaseMap, baseLayerPromises, drawnItems */
/* Lines related to displaying loading bar are commented */ /* Lines related to displaying loading bar are commented */
...@@ -18,8 +18,8 @@ let baseLayerPromises = []; ...@@ -18,8 +18,8 @@ let baseLayerPromises = [];
baseLayerCounter = 0, baseLayerCounter = 0,
currentBaseLayer = 1;*/ currentBaseLayer = 1;*/
let drawnItems; //let drawnItems;
let od, flowMapsArray = []; let od, flowMapsArray = [], odData = {};
/*Object.keys(baseFileSize).forEach((name) => { /*Object.keys(baseFileSize).forEach((name) => {
if (name.split(".")[1] == "zip") { if (name.split(".")[1] == "zip") {
...@@ -29,6 +29,10 @@ let od, flowMapsArray = []; ...@@ -29,6 +29,10 @@ let od, flowMapsArray = [];
} }
});*/ });*/
function compare(el1, el2, index) {
return el1[index] == el2[index] ? 0 : (el1[index] < el2[index] ? -1 : 1);
}
// function to read compressed json and create a leaflet layer // function to read compressed json and create a leaflet layer
const zip2Lyr = (zipFile, layerName, layerTemplate) => { const zip2Lyr = (zipFile, layerName, layerTemplate) => {
baseLayerPromises.push( baseLayerPromises.push(
...@@ -924,6 +928,39 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -924,6 +928,39 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
}); });
$.getJSON(geojson, data => { $.getJSON(geojson, data => {
// build data array from geojson to be used in amchart
let source = data.features;
let newData = [];
source.forEach(o => newData.push({'xVar': o.properties.muni_origen, 'yVar': o.properties.muni_destino, 'flowCount': o.properties.viajes}) );
let origins= [],
destinations = [];
newData.forEach( data => {
origins.push(data.xVar); // all origins
destinations.push(data.yVar) // all destinations
});
origins = origins.filter((v, i, a) => a.indexOf(v) === i); // get unique ones
destinations = destinations.filter((v, i, a) => a.indexOf(v) === i); // get unique ones
// add missing combinations with 0 trips
origins.forEach( (o) => {
destinations.forEach( (d) => {
if (!newData.some( data => data.xVar === o && data.yVar === d ) ) {
newData.push({'xVar': o, 'yVar': d, 'flowCount': 0});
}
})
});
// sort array by origins and then by destinations
newData.sort( (el1,el2) => {
let compared = compare(el1, el2, "xVar")
return compared == 0 ? compare(el1, el2, "yVar") : compared;
});
odData[type] = newData; // push to chart data object to reuse
// TODO: add heatColors to each data array
let flowMapLayer = L.canvasFlowmapLayer(data, { let flowMapLayer = L.canvasFlowmapLayer(data, {
// Define origins and destination from json values // Define origins and destination from json values
originAndDestinationFieldIds: { originAndDestinationFieldIds: {
...@@ -989,9 +1026,11 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -989,9 +1026,11 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
return label[0].properties.nombre; return label[0].properties.nombre;
}) })
// if layer is to be added to on creation, add click funcionality // if layer is to be added on creation, add click funcionality and populate chart
if (addOnCreate) { if (addOnCreate) {
flowMapLayer.addTo(map).on('click', odClick); flowMapLayer.addTo(map).on('click', odClick);
let amchart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "amchartdiv");
amchart.data = newData;
} }
flowMapsArray.push(flowMapLayer); flowMapsArray.push(flowMapLayer);
resolve(flowMapsArray); resolve(flowMapsArray);
...@@ -1114,9 +1153,12 @@ const makeBaseMap = () => { ...@@ -1114,9 +1153,12 @@ const makeBaseMap = () => {
} }
}); });
layer._resetCanvas(); layer._resetCanvas();
$("#tblViajesDesde tbody").html(""); $("#tblViajes tbody").html("");
} }
}); });
// TODO: reset amchart
//let amchart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "amchartdiv")
//amchart.data = odData.ocupadosDesde;
}); });
//resolve(layers); //resolve(layers);
}); });
......
This diff is collapsed.
/* /*
* Copyright 2019 - All rights reserved. * Copyright 2019-2020 - All rights reserved.
* Rodrigo Tapia-McClung * Rodrigo Tapia-McClung
* *
* August-September 2019 * August 2019 - June 2020
*/ */
/* globals omnivore, Promise, chroma, makeBaseMap, makeIndicatorGraph, getData, getDataInSelection */ /* globals omnivore, Promise, chroma, makeBaseMap, makeIndicatorGraph, getData, getDataInSelection */
...@@ -71,7 +71,7 @@ let intervals = { ...@@ -71,7 +71,7 @@ let intervals = {
}, },
"ocupadosHacia": { "ocupadosHacia": {
"classes": ["Menos de 1,000", "1,001 - 2,000", "2,001 - 6,000", "6,001 - 32,000", "32,001 - 53,300"], "classes": ["Menos de 1,000", "1,001 - 2,000", "2,001 - 6,000", "6,001 - 32,000", "32,001 - 53,300"],
"values" : [1000, 2000, 6000, 32000, 533000], "values" : [1000, 2000, 6000, 32000, 53300],
"colors": ["#ffbee8", "#ff73df", "#ff00c5", "#ad027d", "#80006b"], "colors": ["#ffbee8", "#ff73df", "#ff00c5", "#ad027d", "#80006b"],
"thickness": [0.5, 1.5, 2, 4, 10], "thickness": [0.5, 1.5, 2, 4, 10],
"animThickness": [0.5, 1.5, 4, 10, 15] "animThickness": [0.5, 1.5, 4, 10, 15]
...@@ -423,9 +423,10 @@ const odClick = (e) => { ...@@ -423,9 +423,10 @@ const odClick = (e) => {
e.target.selectFeaturesForPathDisplay(dests, "SELECTION_ADD"); e.target.selectFeaturesForPathDisplay(dests, "SELECTION_ADD");
dests.forEach( dest => { dests.forEach( dest => {
//origins += `${dest.properties.muni_origen} &rarr; ${dest.properties.muni_destino}: ${dest.properties.viajes} viajes <br>`; //origins += `${dest.properties.muni_origen} &rarr; ${dest.properties.muni_destino}: ${dest.properties.viajes} viajes <br>`;
origins += `<tr><td>${dest.properties.muni_origen}</td><td>${dest.properties.muni_destino}</td><td>${dest.properties.viajes}</td></tr>`; // style viajes thousands with #,###
origins += `<tr><td>${dest.properties.muni_origen}</td><td>${dest.properties.muni_destino}</td><td>${dest.properties.viajes.toLocaleString()}</td></tr>`;
}); });
$("#tblViajesDesde tbody").html(origins); $("#tblViajes tbody").html(origins);
if (e.sharedDestinationFeatures.length) { if (e.sharedDestinationFeatures.length) {
//e.target.selectFeaturesForPathDisplay(e.sharedDestinationFeatures, "SELECTION_ADD"); //e.target.selectFeaturesForPathDisplay(e.sharedDestinationFeatures, "SELECTION_ADD");
...@@ -435,6 +436,8 @@ const odClick = (e) => { ...@@ -435,6 +436,8 @@ const odClick = (e) => {
/*if (e.sharedDestinationFeatures.length) { /*if (e.sharedDestinationFeatures.length) {
e.target.selectFeaturesForPathDisplay(e.sharedDestinationFeatures, "SELECTION_NEW"); e.target.selectFeaturesForPathDisplay(e.sharedDestinationFeatures, "SELECTION_NEW");
}*/ }*/
// TODO: trigger chart update to only draw selected origins and destinations?
} }
const populateMap = async(mapData) => { const populateMap = async(mapData) => {
...@@ -784,7 +787,6 @@ L.timeDimension.layer.Tile = (layer, options) => { ...@@ -784,7 +787,6 @@ L.timeDimension.layer.Tile = (layer, options) => {
return new L.TimeDimension.Layer.Tile(layer, options); return new L.TimeDimension.Layer.Tile(layer, options);
}; };
// When selecting indicator from dropdown, style tiles. // When selecting indicator from dropdown, style tiles.
$("#indicatorSelect").on("change", function() { $("#indicatorSelect").on("change", function() {
// style currentTiles // style currentTiles
...@@ -806,6 +808,10 @@ $("#indicatorSelect").on("change", function() { ...@@ -806,6 +808,10 @@ $("#indicatorSelect").on("change", function() {
} }
}); });
// on select, update chart data
let amchart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "amchartdiv")
amchart.data = odData[option];
styleTiles(option, minIndicators, maxIndicators) styleTiles(option, minIndicators, maxIndicators)
.then(legend.addTo(map)); // add legend control -> it updates .then(legend.addTo(map)); // add legend control -> it updates
// FIXME: re-adding control updates its contents... why? // FIXME: re-adding control updates its contents... why?
......
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