Commit 94fcb056 authored by Tania Gómez's avatar Tania Gómez

Chords diagram plot

parent 8884b2e5
...@@ -19,7 +19,8 @@ let baseLayerPromises = []; ...@@ -19,7 +19,8 @@ let baseLayerPromises = [];
currentBaseLayer = 1;*/ currentBaseLayer = 1;*/
//let drawnItems; //let drawnItems;
let od, flowMapsArray = [], odData = {}; let od, flowMapsArray = [],
odData = {};
/*Object.keys(baseFileSize).forEach((name) => { /*Object.keys(baseFileSize).forEach((name) => {
if (name.split(".")[1] == "zip") { if (name.split(".")[1] == "zip") {
...@@ -900,9 +901,9 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -900,9 +901,9 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
animatedCanvasBezierStyle = []; animatedCanvasBezierStyle = [];
// define styles based on properties and values // define styles based on properties and values
intervals[type].values.forEach( (val, idx) => { intervals[type].values.forEach((val, idx) => {
canvasBezierStyle.push({ canvasBezierStyle.push({
classMinValue: idx == 0 ? 0 : intervals[type].values[idx-1] + 1, classMinValue: idx == 0 ? 0 : intervals[type].values[idx - 1] + 1,
classMaxValue: val, classMaxValue: val,
symbol: { symbol: {
strokeStyle: intervals[type].colors[idx], strokeStyle: intervals[type].colors[idx],
...@@ -914,7 +915,7 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -914,7 +915,7 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
}); });
animatedCanvasBezierStyle.push({ animatedCanvasBezierStyle.push({
classMinValue: idx == 0 ? 0 : intervals[type].values[idx-1] + 1, classMinValue: idx == 0 ? 0 : intervals[type].values[idx - 1] + 1,
classMaxValue: val, classMaxValue: val,
symbol: { symbol: {
strokeStyle: intervals[type].colors[idx], strokeStyle: intervals[type].colors[idx],
...@@ -931,12 +932,12 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -931,12 +932,12 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
// build data array from geojson to be used in amchart // build data array from geojson to be used in amchart
let source = data.features; let source = data.features;
let newData = []; let newData = [];
source.forEach(o => newData.push({'xVar': o.properties.muni_origen, 'yVar': o.properties.muni_destino, 'flowCount': o.properties.viajes}) ); source.forEach(o => newData.push({ 'xVar': o.properties.muni_origen, 'yVar': o.properties.muni_destino, 'flowCount': o.properties.viajes }));
let origins= [], let origins = [],
destinations = []; destinations = [];
newData.forEach( data => { newData.forEach(data => {
origins.push(data.xVar); // all origins origins.push(data.xVar); // all origins
destinations.push(data.yVar) // all destinations destinations.push(data.yVar) // all destinations
}); });
...@@ -944,16 +945,16 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -944,16 +945,16 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
destinations = destinations.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 // add missing combinations with 0 trips
origins.forEach( (o) => { origins.forEach((o) => {
destinations.forEach( (d) => { destinations.forEach((d) => {
if (!newData.some( data => data.xVar === o && data.yVar === d ) ) { if (!newData.some(data => data.xVar === o && data.yVar === d)) {
newData.push({'xVar': o, 'yVar': d, 'flowCount': 0}); newData.push({ 'xVar': o, 'yVar': d, 'flowCount': 0 });
} }
}) })
}); });
// sort array by origins and then by destinations // sort array by origins and then by destinations
newData.sort( (el1,el2) => { newData.sort((el1, el2) => {
let compared = compare(el1, el2, "xVar") let compared = compare(el1, el2, "xVar")
return compared == 0 ? compare(el1, el2, "yVar") : compared; return compared == 0 ? compare(el1, el2, "yVar") : compared;
}); });
...@@ -989,7 +990,7 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -989,7 +990,7 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
}, },
// dot styles // dot styles
style: function (geoJsonFeature) { style: function(geoJsonFeature) {
if (geoJsonFeature.properties.isOrigin) { if (geoJsonFeature.properties.isOrigin) {
return { return {
renderer: canvasPointRenderer, renderer: canvasPointRenderer,
...@@ -1020,9 +1021,9 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -1020,9 +1021,9 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
animationDuration: 2000, animationDuration: 2000,
customLayerId: type, customLayerId: type,
pane: "pane_flujos" pane: "pane_flujos"
}).bindTooltip( layer => { // what to display on hover }).bindTooltip(layer => { // what to display on hover
let coords = layer.getLatLng(); let coords = layer.getLatLng();
let label = od.features.filter( f => f.properties.lng == coords.lng && f.properties.lat == coords.lat); let label = od.features.filter(f => f.properties.lng == coords.lng && f.properties.lat == coords.lat);
return label[0].properties.nombre; return label[0].properties.nombre;
}) })
...@@ -1031,6 +1032,10 @@ const createFlowLayer = (geojson, type, addOnCreate) => { ...@@ -1031,6 +1032,10 @@ const createFlowLayer = (geojson, type, addOnCreate) => {
flowMapLayer.addTo(map).on('click', odClick); flowMapLayer.addTo(map).on('click', odClick);
let amchart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "amchartdiv"); let amchart = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "amchartdiv");
amchart.data = newData; amchart.data = newData;
let amchart2 = am4core.registry.baseSprites.find(c => c.htmlContainer.id === "prueba2");
amchart2.data = newData;
amchart2.data = amchart2.data.filter(function(e) { return e.flowCount > 0 });
} }
flowMapsArray.push(flowMapLayer); flowMapsArray.push(flowMapLayer);
resolve(flowMapsArray); resolve(flowMapsArray);
...@@ -1135,15 +1140,15 @@ const makeBaseMap = () => { ...@@ -1135,15 +1140,15 @@ const makeBaseMap = () => {
// create one flow, then another, then another... // create one flow, then another, then another...
// and finally set reset control funcionality // and finally set reset control funcionality
createFlowLayer("data/viajes_ocupados_desde.geojson", "ocupadosDesde", true) createFlowLayer("data/viajes_ocupados_desde.geojson", "ocupadosDesde", true)
.then( () => createFlowLayer("data/viajes_ocupados_hacia.geojson", "ocupadosHacia") ) .then(() => createFlowLayer("data/viajes_ocupados_hacia.geojson", "ocupadosHacia"))
.then( () => createFlowLayer("data/viajes_ocupados_entre.geojson", "ocupadosEntre") ) .then(() => createFlowLayer("data/viajes_ocupados_entre.geojson", "ocupadosEntre"))
.then( () => createFlowLayer("data/viajes_ocupados_POIC_desde.geojson", "poicDesde") ) .then(() => createFlowLayer("data/viajes_ocupados_POIC_desde.geojson", "poicDesde"))
.then( () => createFlowLayer("data/viajes_ocupados_POIC_hacia.geojson", "poicHacia") ) .then(() => createFlowLayer("data/viajes_ocupados_POIC_hacia.geojson", "poicHacia"))
.then( () => createFlowLayer("data/viajes_ocupados_POIC_entre.geojson", "poicEntre") ) .then(() => createFlowLayer("data/viajes_ocupados_POIC_entre.geojson", "poicEntre"))
.then( layers => { .then(layers => {
// reset to all flows displayed // reset to all flows displayed
$("#resetFlows").on("click", () => { $("#resetFlows").on("click", () => {
layers.forEach( layer => { layers.forEach(layer => {
if (map.hasLayer(layer)) { if (map.hasLayer(layer)) {
layer.originAndDestinationGeoJsonPoints.features.forEach(function(feature) { layer.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
if (feature.properties.isOrigin === true) { if (feature.properties.isOrigin === true) {
......
...@@ -40,23 +40,23 @@ am4core.ready(function() { ...@@ -40,23 +40,23 @@ am4core.ready(function() {
//heatLegend.minValue = minValue; //heatLegend.minValue = minValue;
//heatLegend.maxValue = maxValue; //heatLegend.maxValue = maxValue;
heatLegend.minValue = 0; heatLegend.minValue = 0;
heatLegend.maxValue = intervals[option].values[intervals[option].values.length-1]; heatLegend.maxValue = intervals[option].values[intervals[option].values.length - 1];
// update heatLegend colors // update heatLegend colors
let heatColors = []; let heatColors = [];
["#333", ...intervals[option].colors].forEach( c => heatColors.push(am4core.color(c)) ); ["#333", ...intervals[option].colors].forEach(c => heatColors.push(am4core.color(c)));
heatLegend.minColor = heatColors[0]; heatLegend.minColor = heatColors[0];
heatLegend.maxColor = heatColors[intervals[option].colors.length - 1]; heatLegend.maxColor = heatColors[intervals[option].colors.length - 1];
//let checkConditions = [minValue, ...intervals[option].values.slice(1)]; //let checkConditions = [minValue, ...intervals[option].values.slice(1)];
let checkConditions = [minValue, ...intervals[option].values]; let checkConditions = [minValue, ...intervals[option].values];
let lastValue = intervals[option].values[intervals[option].values.length-1] let lastValue = intervals[option].values[intervals[option].values.length - 1]
// Override heatLegend gradient // Override heatLegend gradient
let gradient = new am4core.LinearGradient(); let gradient = new am4core.LinearGradient();
heatColors.forEach(function(color, index) { heatColors.forEach(function(color, index) {
// addColor(color, opacity, offset) use offset to put colors in proper alignment // addColor(color, opacity, offset) use offset to put colors in proper alignment
gradient.addColor(color, undefined, (checkConditions[index] - checkConditions[0])/lastValue); gradient.addColor(color, undefined, (checkConditions[index] - checkConditions[0]) / lastValue);
}); });
//heatLegend.markers.template.applyOnClones = true; //heatLegend.markers.template.applyOnClones = true;
...@@ -70,14 +70,14 @@ am4core.ready(function() { ...@@ -70,14 +70,14 @@ am4core.ready(function() {
let workingValue = column.dataItem.values["value"].workingValue; let workingValue = column.dataItem.values["value"].workingValue;
// use min max values calculated from data on beforedatavalidated // use min max values calculated from data on beforedatavalidated
if (am4core.type.isNumber(workingValue)) { if (am4core.type.isNumber(workingValue)) {
checkConditions.forEach( (condition, index) => { checkConditions.forEach((condition, index) => {
if ( index < checkConditions.length-1 ) { if (index < checkConditions.length - 1) {
if (workingValue >= condition && workingValue <= checkConditions[index+1]) { if (workingValue >= condition && workingValue <= checkConditions[index + 1]) {
//console.log(`${workingValue} entre ${condition} y ${checkConditions[index+1]}`) //console.log(`${workingValue} entre ${condition} y ${checkConditions[index+1]}`)
fill = new am4core.Color( fill = new am4core.Color(
am4core.colors.interpolate( am4core.colors.interpolate(
heatColors[index].rgb, heatColors[index].rgb,
heatColors[index+1].rgb, heatColors[index + 1].rgb,
workingValue workingValue
) )
); );
...@@ -119,7 +119,7 @@ am4core.ready(function() { ...@@ -119,7 +119,7 @@ am4core.ready(function() {
xAxis.events.on("sizechanged", function(ev) { xAxis.events.on("sizechanged", function(ev) {
let axis = ev.target; let axis = ev.target;
let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex); let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = 2*Math.ceil(cellWidth)*0.8; axis.renderer.labels.template.maxWidth = 2 * Math.ceil(cellWidth) * 0.8;
}); });
// on data change change, resize labels // on data change change, resize labels
...@@ -127,7 +127,7 @@ am4core.ready(function() { ...@@ -127,7 +127,7 @@ am4core.ready(function() {
xAxis.events.on("datarangechanged", function(ev) { xAxis.events.on("datarangechanged", function(ev) {
let axis = ev.target; let axis = ev.target;
let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex); let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
axis.renderer.labels.template.maxWidth = 2*Math.ceil(cellWidth)*0.8; axis.renderer.labels.template.maxWidth = 2 * Math.ceil(cellWidth) * 0.8;
}); });
xAxis.renderer.labels.template.fontSize = 12; xAxis.renderer.labels.template.fontSize = 12;
...@@ -184,7 +184,7 @@ am4core.ready(function() { ...@@ -184,7 +184,7 @@ am4core.ready(function() {
columnTemplate.adapter.add("strokeWidth", function(width, column) { columnTemplate.adapter.add("strokeWidth", function(width, column) {
var workingValue = column.dataItem.values["value"].workingValue; var workingValue = column.dataItem.values["value"].workingValue;
if (am4core.type.isNumber(workingValue)) { if (am4core.type.isNumber(workingValue)) {
width = workingValue != 0 ? 1: 0; width = workingValue != 0 ? 1 : 0;
} }
return width; return width;
}); });
...@@ -227,8 +227,7 @@ am4core.ready(function() { ...@@ -227,8 +227,7 @@ am4core.ready(function() {
column.strokeWidth = 2; column.strokeWidth = 2;
column.strokeOpacity = 0.2; column.strokeOpacity = 0.2;
heatLegend.valueAxis.showTooltipAt(column.dataItem.value); heatLegend.valueAxis.showTooltipAt(column.dataItem.value);
} } else {
else {
column.strokeWidth = 0; column.strokeWidth = 0;
column.strokeOpacity = 0; column.strokeOpacity = 0;
heatLegend.valueAxis.hideTooltip(); heatLegend.valueAxis.hideTooltip();
...@@ -246,4 +245,85 @@ am4core.ready(function() { ...@@ -246,4 +245,85 @@ am4core.ready(function() {
chart.responsive.enabled = true; chart.responsive.enabled = true;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++CC
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
var cd_chart = am4core.create("prueba2", am4charts.ChordDiagram);
var cd_title = cd_chart.titles.create();
//cd_title.text = "Viajes de ocupados desde centros de mercado";
cd_title.fill = am4core.color(mainTextColor);
cd_title.fontSize = 13;
cd_title.align = "left";
cd_title.marginBottom = 20;
cd_title.paddingLeft = 10;
cd_chart.events.on("beforedatavalidated", function(ev) {
let option = $("#indicatorSelect").val();
let optionTitle = $("#indicatorSelect option:selected").text();
cd_title.text = "[bold]Conectividad origen -destino entre \n" + optionTitle.toLowerCase();
//var data = ev.target.data;
//let data = data.filter(function(e) { return e.flowCount > 0 });
//console.log(data);
});
cd_chart.dataFields.fromName = "xVar";
cd_chart.dataFields.toName = "yVar";
cd_chart.dataFields.value = "flowCount";
//cd_chart.labels.fontSize = 15;
// make nodes draggable
var nodeTemplate = cd_chart.nodes.template;
nodeTemplate.readerTitle = "Oculta/muestra para reorganizar la red"; //"Click to show/hide or drag to rearrange";
nodeTemplate.showSystemTooltip = true;
var nodeLink = cd_chart.links.template;
var bullet = nodeLink.bullets.push(new am4charts.CircleBullet());
bullet.fillOpacity = 0.8;
bullet.circle.radius = 3;
bullet.locationX = 0.5;
// create animations
cd_chart.events.on("over", function() {
// nodeTemplate.events.on("ready", function() {
for (var i = 0; i < cd_chart.links.length; i++) {
var link = cd_chart.links.getIndex(i);
var bullet = link.bullets.getIndex(0);
animateBullet(bullet);
}
})
function animateBullet(bullet) {
var duration = 3000 * Math.random() + 2000;
var animation = bullet.animate([{ property: "locationX", from: 0, to: 1 }], duration)
animation.events.on("animationended", function(event) {
animateBullet(event.target.object)
})
}
var label = nodeTemplate.label;
label.relativeRotation = 90;
label.fontSize = 10;
label.fill = am4core.color(mainTextColor);
//label.wrap = true;
//label.bent = true;
//cd_chart.responsive.enabled = true;
}); // end am4core.ready() }); // end am4core.ready()
\ No newline at end of file
This diff is collapsed.
...@@ -494,4 +494,4 @@ am4core.ready(function() { ...@@ -494,4 +494,4 @@ am4core.ready(function() {
}); // end am4core.ready()*/ }); // end am4core.ready */
\ No newline at end of file \ 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