Commit 0b8693b1 authored by Rodrigo Tapia-McClung's avatar Rodrigo Tapia-McClung

Agricultural tiles on riesgos map

parent c2d6f18a
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* August 2019 * August 2019
*/ */
/* global baseFileSize, formatBytes, Promise, omnivore, JSZip, map, layerControl, updateCharts */ /* global baseFileSize, formatBytes, Promise, omnivore, JSZip, map, glmap, layerControl, updateCharts */
/* exported makeBaseMap, baseLayerPromises, drawnItems */ /* exported makeBaseMap, baseLayerPromises, drawnItems */
/* Lines related to displaying loading bar are commented */ /* Lines related to displaying loading bar are commented */
...@@ -95,17 +95,6 @@ const getCommerceColor = s => { ...@@ -95,17 +95,6 @@ const getCommerceColor = s => {
"#c0d1e5"; "#c0d1e5";
} }
const getCultivoColor = s => {
return s == "Sorgo grano" ? "#ff5500" :
s == "Frijol" ? "#8e1973" :
"#d1ff73";
}
const getCultivoBorder = s => {
return s == "Sorgo grano" ? "#e60000" : // :
s == "Frijol" ? "#a80084" :
"#aaff00"; //;
}
const getPoblacionColor = s => { const getPoblacionColor = s => {
return s > 6000 ? "#6b0601" : return s > 6000 ? "#6b0601" :
s > 4000 ? "#9e4410" : s > 4000 ? "#9e4410" :
...@@ -209,7 +198,7 @@ let layer_pistasaereas = new L.geoJson(null, { ...@@ -209,7 +198,7 @@ let layer_pistasaereas = new L.geoJson(null, {
//pane: "pane_aeropuertosypistas", //pane: "pane_aeropuertosypistas",
minZoom: 9, minZoom: 9,
//onEachFeature: pop_escuelas, //onEachFeature: pop_escuelas,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -225,7 +214,7 @@ let layer_pistasaereas = new L.geoJson(null, { ...@@ -225,7 +214,7 @@ let layer_pistasaereas = new L.geoJson(null, {
borderWidth: 0, borderWidth: 0,
borderColor: "transparent", borderColor: "transparent",
backgroundColor: "transparent" //, backgroundColor: "transparent" //,
// textColor: "#C0C0C0" // textColor: "#C0C0C0"
}); });
return new L.Marker(latlng, { return new L.Marker(latlng, {
icon: avionMarker icon: avionMarker
...@@ -242,7 +231,7 @@ let layer_autobuses = new L.geoJson(null, { ...@@ -242,7 +231,7 @@ let layer_autobuses = new L.geoJson(null, {
attribution: "", attribution: "",
pane: "pane_autobuses", pane: "pane_autobuses",
//onEachFeature: pop_escuelas, //onEachFeature: pop_escuelas,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -258,7 +247,7 @@ let layer_autobuses = new L.geoJson(null, { ...@@ -258,7 +247,7 @@ let layer_autobuses = new L.geoJson(null, {
borderWidth: 0, borderWidth: 0,
borderColor: "transparent", borderColor: "transparent",
backgroundColor: "transparent" //, backgroundColor: "transparent" //,
// textColor: "#C0C0C0" // textColor: "#C0C0C0"
}); });
return new L.Marker(latlng, { return new L.Marker(latlng, {
icon: busMarker icon: busMarker
...@@ -270,7 +259,7 @@ let layer_supermercados = new L.geoJson(null, { ...@@ -270,7 +259,7 @@ let layer_supermercados = new L.geoJson(null, {
attribution: "", attribution: "",
pane: "pane_supermercados", pane: "pane_supermercados",
//onEachFeature: pop_escuelas, //onEachFeature: pop_escuelas,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -298,7 +287,7 @@ let layer_bancos = new L.geoJson(null, { ...@@ -298,7 +287,7 @@ let layer_bancos = new L.geoJson(null, {
attribution: "", attribution: "",
pane: "pane_bancos", pane: "pane_bancos",
//onEachFeature: pop_escuelas, //onEachFeature: pop_escuelas,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -326,7 +315,7 @@ let layer_escuelas = new L.geoJson(null, { ...@@ -326,7 +315,7 @@ let layer_escuelas = new L.geoJson(null, {
attribution: "", attribution: "",
pane: "pane_escuelas", pane: "pane_escuelas",
//onEachFeature: pop_escuelas, //onEachFeature: pop_escuelas,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -353,7 +342,7 @@ let layer_hospitales = new L.geoJson(null, { ...@@ -353,7 +342,7 @@ let layer_hospitales = new L.geoJson(null, {
attribution: "", attribution: "",
pane: "pane_hospitales", pane: "pane_hospitales",
//onEachFeature: pop_hospitales, //onEachFeature: pop_hospitales,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -381,7 +370,7 @@ let layer_hoteles = new L.geoJson(null, { ...@@ -381,7 +370,7 @@ let layer_hoteles = new L.geoJson(null, {
attribution: "", attribution: "",
pane: "pane_hoteles", pane: "pane_hoteles",
//onEachFeature: pop_hoteles, //onEachFeature: pop_hoteles,
pointToLayer: function(feature, latlng) { pointToLayer: (_feature, latlng) => {
// let context = { // let context = {
// feature: feature, // feature: feature,
// variables: {} // variables: {}
...@@ -447,34 +436,34 @@ let layer_limZMs = new L.geoJson(null, { ...@@ -447,34 +436,34 @@ let layer_limZMs = new L.geoJson(null, {
const style_ZMs = feature => { const style_ZMs = feature => {
switch (String(feature.properties["ZM_NOMBRE"])) { switch (String(feature.properties["ZM_NOMBRE"])) {
case "Tuxtla Gutiérrez": case "Tuxtla Gutiérrez":
return { return {
pane: "pane_ZMs", pane: "pane_ZMs",
opacity: 1, opacity: 1,
color: "rgba(139,47,0,0.6)", color: "rgba(139,47,0,0.6)",
dashArray: "", dashArray: "",
lineCap: "butt", lineCap: "butt",
lineJoin: "miter", lineJoin: "miter",
weight: 1.0, weight: 1.0,
fill: true, fill: true,
fillOpacity: 1, fillOpacity: 1,
fillColor: "rgba(139,60,0,0.6)" fillColor: "rgba(139,60,0,0.6)"
} }
//break; //break;
case "Villahermosa": case "Villahermosa":
return { return {
pane: "pane_ZMs", pane: "pane_ZMs",
opacity: 1, opacity: 1,
color: "rgba(139,47,0,0.6)", color: "rgba(139,47,0,0.6)",
dashArray: "", dashArray: "",
lineCap: "butt", lineCap: "butt",
lineJoin: "miter", lineJoin: "miter",
weight: 1.0, weight: 1.0,
fill: true, fill: true,
fillOpacity: 1, fillOpacity: 1,
fillColor: "rgba(207,152,62,0.6)" fillColor: "rgba(207,152,62,0.6)"
} }
//break; //break;
} }
} }
...@@ -529,50 +518,67 @@ let layer_agebsbydens = new L.geoJson(null, { ...@@ -529,50 +518,67 @@ let layer_agebsbydens = new L.geoJson(null, {
style: style_agebsbydens style: style_agebsbydens
}); });
const style_agricolaoi = feature => { const baseUrl = new URL(`/data`, window.location.href).href;
return { let layer_agricolapv_fake = new L.geoJson(null, {}),
pane: "pane_agricolaoi", layer_agricolaoi_fake = new L.geoJson(null, {});
opacity: 1,
color: getCultivoBorder(feature.properties['CULTIVO']), let layer_agricolapv = {
//dashArray: "3 2", id: "agricola_pv",
lineCap: "butt", source: {
lineJoin: "miter", type: "vector",
weight: 0.5, //1.0, tiles: [`${baseUrl}/agricola_pv/mvt/{z}/{x}/{y}?geom_column=geom&columns=cultivo`],
fill: true, maxzoom: 19,
fillOpacity: 1, minzoom: 6
fillColor: getCultivoColor(feature.properties['CULTIVO']) },
"source-layer": "agricola_pv", // source has to match postgi table name
type: "fill",
paint: {
"fill-opacity": 0,
"fill-color": [
"match",
["get", "cultivo"],
"Sorgo grano", "#ff5500",
"Frijol", "#8e1973",
"#d1ff73"
],
"fill-outline-color": [
"match",
["get", "cultivo"],
"Sorgo grano", "#e60000",
"Frijol", "#a80084",
"#aaff00"
]
} }
} }
let layer_agricolaoi = new L.geoJson(null, { let layer_agricolaoi = {
attribution: "", id: "agricola_oi",
pane: "pane_agricolaoi", source: {
//onEachFeature: pop_ANPs, type: "vector",
style: style_agricolaoi tiles: [`${baseUrl}/agricola_oi/mvt/{z}/{x}/{y}?geom_column=geom&columns=cultivo`],
}); maxzoom: 19,
minzoom: 6
const style_agricolapv = feature => { },
return { "source-layer": "agricola_oi", // source has to match postgi table name
pane: "pane_agricolapv", type: "fill",
opacity: 1, paint: {
color: getCultivoBorder(feature.properties['CULTIVO']), "fill-opacity": 0,
//dashArray: "3 2", "fill-color": [
lineCap: "butt", "match",
lineJoin: "miter", ["get", "cultivo"],
weight: 0.5, //1.0, "Sorgo grano", "#ff5500",
fill: true, "Frijol", "#8e1973",
fillOpacity: 1, "#d1ff73"
fillColor: getCultivoColor(feature.properties['CULTIVO']) ],
"fill-outline-color": [
"match",
["get", "cultivo"],
"Sorgo grano", "#e60000",
"Frijol", "#a80084",
"#aaff00"
]
} }
} }
let layer_agricolapv = new L.geoJson(null, {
attribution: "",
pane: "pane_agricolapv",
//onEachFeature: pop_ANPs,
style: style_agricolaoi
});
const styleDrawnItems = () => { const styleDrawnItems = () => {
let currentId = 0; let currentId = 0;
drawnItems.eachLayer(l => { drawnItems.eachLayer(l => {
...@@ -655,10 +661,12 @@ const makeBaseMap = () => { ...@@ -655,10 +661,12 @@ const makeBaseMap = () => {
zip2Lyr("../riesgos/data/Bancos.zip", bancos, layer_bancos); zip2Lyr("../riesgos/data/Bancos.zip", bancos, layer_bancos);
layerControl.addOverlay(layer_bancos, "<span class = \"fa fa-stack\" style=\"padding-top: 6px;\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:#05ac72;\"></i><i class=\"fas fa-dollar fa-stack-1x fa-inverse\"></i></span>Bancos"); layerControl.addOverlay(layer_bancos, "<span class = \"fa fa-stack\" style=\"padding-top: 6px;\"><i class=\"fas fa-desechos fa-stack-1x\" style=\"color:#05ac72;\"></i><i class=\"fas fa-dollar fa-stack-1x fa-inverse\"></i></span>Bancos");
layerControl.addOverlay(layer_vferreas, "<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/mdm6wms?map=/opt/map/mdm60/mdm61leyendaprueba.map&Request=GetLegendGraphic&format=image/png&Version=1.1.1&Service=WMS&LAYER=c202\" alt=\"Vías Férreas\"/>"); layerControl.addOverlay(layer_vferreas, "<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/mdm6wms?map=/opt/map/mdm60/mdm61leyendaprueba.map&Request=GetLegendGraphic&format=image/png&Version=1.1.1&Service=WMS&LAYER=c202\" alt=\"Vías Férreas\"/>");
zip2Lyr("../riesgos/data/agricola_oi.zip", agricolaoi, layer_agricolaoi); glmap.getMapboxMap().addLayer(layer_agricolaoi);
layerControl.addOverlay(layer_agricolaoi, "Ciclo agrícola (Otoño-Invierno), SIAP-SADER 2017-2018 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d1ff73\" stroke=\"#aaff00\" stroke-dasharray=\" \"></rect></svg> Maíz grano<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8e1973\" stroke = \"#a80084\" stroke-dasharray=\" \"></rect></svg> Frijol<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ff5500\" stroke = \"#e60000\" stroke-dasharray=\" \"></rect></svg> Sorgo grano"); layerControl.addOverlay(layer_agricolaoi_fake, "Ciclo agrícola (Otoño-Invierno), SIAP-SADER 2017-2018 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d1ff73\" stroke=\"#aaff00\" stroke-dasharray=\" \"></rect></svg> Maíz grano<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8e1973\" stroke = \"#a80084\" stroke-dasharray=\" \"></rect></svg> Frijol<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ff5500\" stroke = \"#e60000\" stroke-dasharray=\" \"></rect></svg> Sorgo grano");
// zip2Lyr("../riesgos/data/agricola_pv.zip", agricolapv, layer_agricolapv); //map.addLayer(layer_agricolaoi_fake);
// layerControl.addOverlay(layer_agricolapv, "Ciclo agrícola (Primavera-Verano), SIAP-SADER 2017 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d1ff73\" stroke=\"#aaff00\" stroke-dasharray=\" \"></rect></svg> Maíz grano<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8e1973\" stroke = \"#a80084\" stroke-dasharray=\" \"></rect></svg> Frijol<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ff5500\" stroke = \"#e60000\" stroke-dasharray=\" \"></rect></svg> Sorgo grano"); glmap.getMapboxMap().addLayer(layer_agricolapv);
//map.addLayer(layer_agricolapv_fake);
layerControl.addOverlay(layer_agricolapv_fake, "Ciclo agrícola (Primavera-Verano), SIAP-SADER 2017 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d1ff73\" stroke=\"#aaff00\" stroke-dasharray=\" \"></rect></svg> Maíz grano<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8e1973\" stroke = \"#a80084\" stroke-dasharray=\" \"></rect></svg> Frijol<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ff5500\" stroke = \"#e60000\" stroke-dasharray=\" \"></rect></svg> Sorgo grano");
zip2Lyr("../riesgos/data/poblacionAGEB.zip", agebsbydens, layer_agebsbydens); zip2Lyr("../riesgos/data/poblacionAGEB.zip", agebsbydens, layer_agebsbydens);
layerControl.addOverlay(layer_agebsbydens, "Densidad de población total por AGEB <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffffff\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> Sin Población<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#f1f0fc\" stroke = \"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 1 - 2400 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d2d3fa\" stroke = \"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 2401 - 7000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height =\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#a6a2eb\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 7001 - 11500 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height =\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8c6fbd\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 11501 - 16000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height =\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#633096\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 16001 - 67000"); layerControl.addOverlay(layer_agebsbydens, "Densidad de población total por AGEB <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#ffffff\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> Sin Población<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height=\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#f1f0fc\" stroke = \"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 1 - 2400 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height = \"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#d2d3fa\" stroke = \"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 2401 - 7000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height =\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#a6a2eb\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 7001 - 11500 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height =\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#8c6fbd\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 11501 - 16000 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<svg height =\"15\" width=\"15\"><path d=\"M0 0 L15 0 L15 10 L0 10 Z \" x=\"5\" y=\"5\" fill=\"#633096\" stroke=\"rgba(0,0,0,0.6)\" stroke-dasharray=\" \"></rect></svg> 16001 - 67000");
zip2Lyr("../riesgos/data/poblacionAGEB.zip", agebsbypop, layer_agebsbypop); zip2Lyr("../riesgos/data/poblacionAGEB.zip", agebsbypop, layer_agebsbypop);
...@@ -674,116 +682,131 @@ const makeBaseMap = () => { ...@@ -674,116 +682,131 @@ const makeBaseMap = () => {
layerControl.addOverlay(layer_limiteMunicipal, "<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=c101&format=image/png&STYLE=default\" alt=\"Límite municipal\"/>"); layerControl.addOverlay(layer_limiteMunicipal, "<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=c101&format=image/png&STYLE=default\" alt=\"Límite municipal\"/>");
layerControl.addOverlay(layer_limiteEstatal, "Límite estatal <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=c100&format=image/png&STYLE=default\" alt=\"Límite Estatal\"/>"); layerControl.addOverlay(layer_limiteEstatal, "Límite estatal <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src=\"http://gaia.inegi.org.mx/NLB/tunnel/wms/wms61?version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer=c100&format=image/png&STYLE=default\" alt=\"Límite Estatal\"/>");
map.on("overlayadd", event => {
if (event.name.includes("Primavera-Verano")) {
glmap.getMapboxMap().setPaintProperty("agricola_pv", "fill-opacity", 1);
}
if (event.name.includes("Otoño-Invierno")) {
glmap.getMapboxMap().setPaintProperty("agricola_oi", "fill-opacity", 1);
}
}).on("overlayremove", event => {
if (event.name.includes("Primavera-Verano")) {
glmap.getMapboxMap().setPaintProperty("agricola_pv", "fill-opacity", 0);
}
if (event.name.includes("Otoño-Invierno")) {
glmap.getMapboxMap().setPaintProperty("agricola_oi", "fill-opacity", 0);
}
})
// Localize Leaflet.Draw texts // Localize Leaflet.Draw texts
L.drawLocal = { L.drawLocal = {
draw: { draw: {
toolbar: { toolbar: {
actions: { actions: {
title: "Cancelar dibujo", title: "Cancelar dibujo",
text: "Cancelar" text: "Cancelar"
}, },
finish: { finish: {
title: "Terminar dibujo", title: "Terminar dibujo",
text: "Terminar" text: "Terminar"
}, },
undo: { undo: {
title: "Eliminar último punto dibujado", title: "Eliminar último punto dibujado",
text: "Eliminar último punto" text: "Eliminar último punto"
},
buttons: {
polyline: "Dibujar una polilínea",
polygon: "Dibujar un polígono",
rectangle: "Dibujar un rectángulo",
circle: "Dibujar un círculo",
marker: "Dibujar un marcador",
circlemarker: "Dibujar un marcador circular"
}
},
handlers: {
circle: {
tooltip: {
start: "Haz click y arrastra para dibujar un círculo"
}, },
buttons: { radius: "Radio"
polyline: "Dibujar una polilínea", },
polygon: "Dibujar un polígono", circlemarker: {
rectangle: "Dibujar un rectángulo", tooltip: {
circle: "Dibujar un círculo", start: "Haz click en el mapa para ubicar el marcador circular"
marker: "Dibujar un marcador",
circlemarker: "Dibujar un marcador circular"
} }
}, },
handlers: { marker: {
circle: { tooltip: {
tooltip: { start: "Haz click en el mapa para ubicar el marcador"
start: "Haz click y arrastra para dibujar un círculo" }
}, },
radius: "Radio" polygon: {
}, error: "<strong>Error:</strong>",
circlemarker: { tooltip: {
tooltip: { start: "Haz click para empezar a dibujar la figura",
start: "Haz click en el mapa para ubicar el marcador circular" cont: "Haz click para continuar dibujando la figura",
} end: "Haz click en el primer punto para cerrar la figura"
}, }
marker: { },
tooltip: { polyline: {
start: "Haz click en el mapa para ubicar el marcador" error: "<strong>Error:</strong> las líneas no deben cruzarse",
} tooltip: {
}, start: "Haz click para empezar a dibujar la línea",
polygon: { cont: "Haz click para continuar dibujando la línea",
error: "<strong>Error:</strong>", end: "Haz click en el último punto para terminar la línea"
tooltip: { }
start: "Haz click para empezar a dibujar la figura", },
cont: "Haz click para continuar dibujando la figura", rectangle: {
end: "Haz click en el primer punto para cerrar la figura" tooltip: {
} start: "Haz click y arrastra para dibujar un rectángulo"
}, }
polyline: { },
error: "<strong>Error:</strong> las líneas no deben cruzarse", simpleshape: {
tooltip: { tooltip: {
start: "Haz click para empezar a dibujar la línea", end: "Suelta el ratón para terminar de dibujar"
cont: "Haz click para continuar dibujando la línea", }
end: "Haz click en el último punto para terminar la línea" }
} }
},
edit: {
toolbar: {
actions: {
save: {
title: "Guardar los cambios",
text: "Guardar"
}, },
rectangle: { cancel: {
tooltip: { title: "Cancelar la edición, descarta todos los cambios",
start: "Haz click y arrastra para dibujar un rectángulo" text: "Cancelar"
}
}, },
simpleshape: { clearAll: {
tooltip: { title: "Limpiar todas las capas",
end: "Suelta el ratón para terminar de dibujar" text: "Limpiar todo"
}
} }
},
buttons: {
edit: "Editar capas",
editDisabled: "No hay capas que editar",
remove: "Eliminar capas",
removeDisabled: "No hay capas que eliminar"
} }
}, },
edit: { handlers: {
toolbar: { edit: {
actions: { tooltip: {
save: { text: "Arrastra el marcador para editar la figura",
title: "Guardar los cambios", subtext: "Haz click en cancelar para deshacer los cambios"
text: "Guardar"
},
cancel: {
title: "Cancelar la edición, descarta todos los cambios",
text: "Cancelar"
},
clearAll: {
title: "Limpiar todas las capas",
text: "Limpiar todo"
}
},
buttons: {
edit: "Editar capas",
editDisabled: "No hay capas que editar",
remove: "Eliminar capas",
removeDisabled: "No hay capas que eliminar"
} }
}, },
handlers: { remove: {
edit: { tooltip: {
tooltip: { text: "Haz click en una figura para eliminarla"
text: "Arrastra el marcador para editar la figura",
subtext: "Haz click en cancelar para deshacer los cambios"
}
},
remove: {
tooltip: {
text: "Haz click en una figura para eliminarla"
}
} }
} }
} }
} }
// leaflet draw control }
// leaflet draw control
drawnItems = L.featureGroup().addTo(map); drawnItems = L.featureGroup().addTo(map);
let drawControl = new L.Control.Draw({ let drawControl = new L.Control.Draw({
......
/*
* Copyright 2019 - All rights reserved.
* Rodrigo Tapia-McClung
*
* August-September 2019
*/
/* globals omnivore, Promise, chroma, makeBaseMap, makeIndicatorGraph, getData, getDataInSelection */
/* exported indicators. userFiles, userDates, timeParse, layerControl, updateCharts */
let timeParse,
timeFormat,
timeDimensionControl,
userFiles = [],
monthArray = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
dateArray = [],
dateMin,
dateMax,
minUserDate,
maxUserDate,
userDates,
map,
overlay,
glmap,
osmLayer, cartoLightLayer, cartoDarkLayer,
timeLayer,
layerControl,
scale;
// define empty objects and indicators
let maxIndicators = {},
minIndicators = {},
indicators = ["area", "perimeter", "costa", "df"],
indicatorsNames = ["Área", "Perímetro", "Desarrollo de la línea de costa", "Dimensión fractal"],
indicatorsUnits = ["m\u00B2", "m", "", ""],
indicatorsxAxisFormat = [".2s", ".2s", ".2f", ".2f"],
indicatorVars = {},
cols = [];
// Add options to combo box, and set their chart variables
// chart containers must already exist in index.php
indicators.forEach( (indicator, index) => {
// colnames for queries
cols.push(`min(${indicator}) as min${indicator}`);
cols.push(`max(${indicator}) as max${indicator}`);
// initialize min and max objects to hold values for each indicator and add select options
maxIndicators[indicator] = 0;
minIndicators[indicator] = 1e30;
$("#indicatorSelect").append(`<option value="${indicator}"> ${indicatorsNames[index]}</option>`);
// chart variables
indicatorVars[indicator] = {
"chart": `${indicator}Chart`,
"chartaData": `${indicator}Data`,
"container": `#${indicator}-graph`
};
});
indicatorVars.area.explanation = "Muestra la suma del &aacute;rea contenida en los pol&iacute;gonos dentro de la selecci&oacute;n o en toda la regi&oacute;n de estudio.";
indicatorVars.perimeter.explanation = "Muestra la suma del per&iacute;metro de los pol&iacute;gonos dentro de la selecci&oacute;n o en toda la regi&oacute;n de estudio.";
indicatorVars.costa.explanation = "Relaciona el per&iacute;metro de un cuerpo de agua o longitud de l&iacute;nea de costa con el per&iacute;metro de un c&iacute;rculo de igual \
&aacute;rea (A) que el cuerpo. El valor m&iacute;nimo es 1, el cual corresponde a un c&iacute;rculo perfecto, mientras que el valor m&aacute;ximo no tiene l&iacute;mite. \
En varios estudios se han obtenido valores mayores de 20, como en algunos lagos en Finlandia. Los valores cercanos a 1 son indicativos de formas circulares, mientras que \
los valores mayores de 3 son referencia de cuerpos de agua con contornos de formas alargadas. \
<br/><br/> \
Se calcula como \
<p class=\"equation\">DI = <span class=\"frac\"><sup>P</sup><span>&frasl;</span><sub>2&radic;<span style=\"text-decoration: overline;\">&pi; A</span></sub></span>,</p> \
donde P es el per&iacute;metro y A es el &aacute;rea.";
indicatorVars.df.explanation = "La geometr&iacute;a fractal se usa para hacer referencia a objetos demasiado irregulares y que tienen la propiedad de ser invariantes ante \
cambios de escala. En el caso de la hidrolog&iacute;a, este &iacute;ndice nos refiere la sinuosidad del contorno de un cuerpo de agua. La dimensi&oacute;n presenta valores \
reales no negativos entre 1 y 2. Los valores de este &iacute;ndice aumentan conforme el contorno del cuerpo de agua es más sinuoso. El an&aacute;lisis fractal se ha utilizado \
con &eacute;xito para medir y caracterizar rasgos lineales irregulares como las costas. \
<br/></br> \
Se calcula como \
<p class=\"equation\">DF = <span class=\"frac\"><sup>2 ln(P/4)</sup><span>&frasl;</span><sub>ln(A)</sub></span>,</p> \
donde P es el per&iacute;metro y A es el &aacute;rea.";
let currentTiles = {},
allTiles = {};
d3.json("https://unpkg.com/d3-time-format@2.1.1/locale/es-MX.json").then(locale => {
d3.timeFormatDefaultLocale(locale);
timeParse = d3.timeParse("%B_%Y");
timeFormat = d3.timeFormat("%B_%Y");
setupTimeDimensionControl();
setupDates()
.then(dates => populateDates(dates))
.then(userData => setupMap(userData))
.then(map => populateMap(map));
});
const sortInitialDateAscending = (a, b) => {
// Dates will be cast to numbers automagically:
return a - b;
}
// query available dates on DB
const setupDates = () => {
return new Promise( resolve => {
const baseUrl = new URL(`/data`, window.location.href).href;
let layersQuery = `${baseUrl}/list_layers`;
d3.json(layersQuery).then(layers => {
layers.forEach(layer => {
dateArray.push(timeParse(layer.f_table_name)); // convert filenames to dates
})
dateArray = dateArray.sort(sortInitialDateAscending); // order dates
dateMin = d3.min(dateArray);
dateMax = d3.max(dateArray);
//userFiles = dateArray.map( month => timeFormat(month)); // order table names by date
const dates = {min:dateMin, max:dateMax, dates:dateArray};
resolve(dates);
});
});
}
const populateDates = (dates) => { // fill out date pickers with available dates
return new Promise( resolve => {
$.datepicker.regional["es"] = {
closeText: "Cerrar",
prevText: "&#x3c;Ant",
nextText: "Sig&#x3e;",
currentText: "Hoy",
monthNames: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
],
monthNamesShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun",
"Jul", "Ago", "Sep", "Oct", "Nov", "Dic"
],
dayNames: ["Domingo", "Lunes", "Martes", "Mi&eacute;rcoles", "Jueves", "Viernes", "S&aacute;bado"],
dayNamesShort: ["Dom", "Lun", "Mar", "Mi&eacute;", "Juv", "Vie", "S&aacute;b"],
dayNamesMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "S&aacute;"],
weekHeader: "Sm",
dateFormat: "yy/mm/dd",
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: ""
}
$.datepicker.setDefaults($.datepicker.regional["es"]);
// month pickers
$("#date-initial").datepicker({
minDate: dates.min,
maxDate: dates.max,
defaultDate: dates.min,
changeMonth: true,
changeYear: true,
showButtonPanel: true,
dateFormat: "M yy",
onClose: function() {
let month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
let year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
minUserDate = new Date(year, month, 1); // initial date
$(this).datepicker("setDate", minUserDate);
$("#date-final").datepicker("option", {
"minDate": minUserDate,
disabled: false
});
// hack to avoid needing to change date twice in second datepicker
setTimeout(() => { $("#date-final").datepicker("show") }, 10);
},
beforeShow: el => {
$("#ui-datepicker-div").toggleClass("hide-calendar", $(el).is("[data-calendar=\"false\"]"));
}
});
$("#date-final").datepicker({
maxDate: dates.max,
defaultDate: dates.max,
changeMonth: true,
changeYear: true,
showButtonPanel: true,
disabled: true,
dateFormat: "M yy",
onClose: function() {
let month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
let year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
maxUserDate = new Date(year, month, 1); // final date
$(this).datepicker("setDate", maxUserDate);
// use .setUTCHours(6,0,0) to adjust DST offset fror some months
let startUserDate = new Date(minUserDate.setUTCHours(6,0,0));
let endUserDate = new Date(maxUserDate.setUTCHours(6,0,0));
// pass new timeinterval to timeDimension player
userDates = L.TimeDimension.Util.explodeTimeRange(startUserDate, endUserDate, "P1M");
userFiles = userDates.map( month => timeFormat(month)); // order table names by date
// change date selectors from main screen to map
$("#date-initial").detach().appendTo("#datePickers");
$("#date-final").detach().appendTo("#datePickers");
$("#datePickers").css("display", "block");
// hide initial screen and show map
$("#startHeader").remove();
$("#initial-backdrop").remove();
$("#mainContainer")[0].style.setProperty("display", "flex", "important")
$("#mexmap").show();
// When closing final-date, either setup or update map
if (!map) {
resolve({min: startUserDate, max: endUserDate});
} else {
// FIXME: no need to pass data here?
updateMap({map: map, min: startUserDate, max: endUserDate});
}
},
beforeShow: (el, inst) => {
inst.input.datepicker("refresh");
$("#ui-datepicker-div").toggleClass("hide-calendar", $(el).is("[data-calendar=\"false\"]"));
}
});
})
}
const setupMap = (dates) => {
return new Promise( resolve => {
// make body tag to have style height: 100%
$("body").css("height", "100%");
osmLayer = L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: "&copy; <a href=\"http://osm.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors"
});
cartoLightLayer = L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: "Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL."
});
cartoDarkLayer = L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: "Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL."
});
//let bounds = cuencaBufferMask.getBounds();
let southWest = L.latLng(15.08, -94.42),
northEast = L.latLng(18.82, -91.52),
bounds = L.latLngBounds(southWest, northEast);
map = L.map("mexmap", {
//center: [17.22, -92.28],
minZoom: 7, //8
zoom: 7, //6
attributionControl: false,
timeDimension: true,
timeDimensionOptions: {
times: userDates,
currentTime: dates.min
},
maxBounds: bounds
}).setView([16.96, -92.97], 8);
cartoDarkLayer.addTo(map);
// set sync map on right
let osmLayerOverlay = L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: "&copy; <a href=\"http://osm.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors"
}),
cartoLightLayerOverlay = L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: "Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL."
}),
cartoDarkLayerOverlay = L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution: "Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL."
});
overlay = L.map("overlaydiv", {
zoomControl: false,
inertia: false,
keyboard: false,
//dragging: false,
scrollWheelZoom: true,
attributionControl: false,
zoomAnimation: true
}).setView([16.96, -92.97], 8);
cartoDarkLayerOverlay.addTo(overlay);
L.control.attribution({position: "bottomright"}).addTo(overlay);
// on base layer on main map, change base layer on overlay map
map.on("baselayerchange", event => {
overlay.eachLayer(l => overlay.removeLayer(l));
if (event.name == "Carto Dark") {
cartoDarkLayerOverlay.addTo(overlay);
} else if (event.name == "Carto Light") {
cartoLightLayerOverlay.addTo(overlay);
} else if (event.name == "OpenStreetMap") {
osmLayerOverlay.addTo(overlay);
}
});
const offsetGlobal = (center, zoom, refMap, tgtMap) => {
var refC = refMap.getContainer();
var tgtC = tgtMap.getContainer();
var pt = refMap.project(center, zoom)
.subtract([refC.offsetLeft, refC.offsetTop])
.subtract(refMap.getSize().divideBy(2))
.add([tgtC.offsetLeft, tgtC.offsetTop])
.add(tgtMap.getSize().divideBy(2));
return refMap.unproject(pt, zoom);
}
map.sync(overlay, {offsetFn: offsetGlobal});
//console.log(userFiles);
// query db to get min/max values per month and indicator and store them in an object
queryFiles().then( minmax => {
minmax.map( minmaxMonth => {
indicators.forEach( (indicator) => {
minIndicators[indicator] = Math.min(minIndicators[indicator], minmaxMonth[`min${indicator}`]);
maxIndicators[indicator] = Math.max(maxIndicators[indicator], minmaxMonth[`max${indicator}`]);
});
});
resolve({"map": map, "minIndicators": minIndicators, "maxIndicators": maxIndicators});
});
});
}
const flatten = arrays => {
return [].concat(arrays);
}
const queryFiles = () => {
return Promise.all(userFiles.map(getMinMax))
// the result is an array of arrays, so we'll flatten them here
.then(flatten);
}
const getMinMax = table => {
return new Promise( resolve => {
const baseUrl = new URL(`/data`, window.location.href).href;
let minmaxQuery = `${baseUrl}/query/${table}?columns=${cols.join(", ")}`;
d3.json(minmaxQuery).then( minmax => {
resolve(minmax[0]);
});
});
}
const populateMap = async (mapData) => {
const chartData = await getData();
// Define charts with reusable components
indicators.map( async (indicator, index) => {
// indicatorVars[indicator].chart gives areaChart, perimeterChart, etc.
// First, make all charts with same general options
indicatorVars[indicator].chart = makeIndicatorGraph()
.width(Math.floor($(indicatorVars[indicator].container)[0].offsetParent.offsetWidth * 0.95))
.height(Math.floor($(indicatorVars[indicator].container)[0].offsetParent.offsetHeight * 0.95))
.lineVariables([`${indicator}0`]) // d.area is used to draw stuff on y axis
.displayName("date") // d.date is used to draw stuff on x axis
.lineAxisLabel("(m)")
.id(indicator)
.xAxisFormat(d3.timeFormat("%b '%y")) // label x axis as mm 'yy
.yAxisFormat(d3.format(indicatorsxAxisFormat[index])) // yAxis label in SI or other
// Then, specify some parameters for each chart
.tooltipUnits(indicatorsUnits[index])
.tooltipFormat(d3.format(indicatorsxAxisFormat[index])) // tooltip format in SI or other
.title(indicatorsUnits[index] == "" ? indicatorsNames[index] :
`${indicatorsNames[index]} (${indicatorsUnits[index]})`);
// Finally, set chart data with async function calling stuff from DB
indicatorVars[indicator].chart.data( chartData[indicator]);
// create chart with passed options
d3.select(indicatorVars[indicator].container)
.call(indicatorVars[indicator].chart);
// Reload chart data and force chart update
indicatorVars[indicator].chartData = indicatorVars[indicator].chart.data(); // get chart data
indicatorVars[indicator].chart.data(indicatorVars[indicator].chartData); // set chart data
// Highlight plot title according to selected option
let option = $("#indicatorSelect").val(); // option selected from dropdrown
d3.select(indicatorVars[option].container).select("svg text.title").classed("active", true);
});
let map = mapData.map,
minIndicators = mapData.minIndicators,
maxIndicators = mapData.maxIndicators;
let cuencaLayer = L.geoJson(null, {
style: {
stroke: true,
weight: 5,
color: "grey",
opacity: .35,
fillOpacity: 0.05
},
interactive: false
});
let cuencaBufferMask = omnivore.topojson("data/buffer_cuenca.topojson", null, cuencaLayer);
cuencaBufferMask.addTo(map);
//map.createPane("wb-Tiles");
//map.getPane("wb-Tiles").style.zIndex = 450;
// create mvt layers
userFiles.forEach( f => {
f = mapboxLayer(f);
});
glmap = L.mapboxGL({
accessToken: "no-token",
style: {
"version": 8,
"sources": {},
"layers": []
}
}).addTo(map);
// after mapboxGL map is ready with styles do this:
glmap.getMapboxMap().on("style.load", () => {
userFiles.forEach(monthYear => {
glmap.getMapboxMap().addLayer(currentTiles[monthYear]);
});
Object.keys(allTiles).forEach(layer => {
if (layer == userFiles[0]) {
glmap.getMapboxMap().setPaintProperty(layer, "fill-opacity", 0.7)
}
});
timeDimensionControl.addTo(map);
// Pass dummy geojson layer to timeDimension in order to register and sync
timeLayer = L.timeDimension.layer.Tile(L.geoJSON(), {
updateTimeDimension: true,
updateTimeDimensionMode: "replace",
waitForReady: true,
duration: "P1M"
});
timeLayer.addTo(map);
// style currentTiles
let option = $("#indicatorSelect").val(); // option selected from dropdrown
styleTiles(option, minIndicators, maxIndicators)
.then(legend.addTo(map)); // add legend control -> it updates
let baseLayers = {
"Carto Dark": cartoDarkLayer,
"Carto Light": cartoLightLayer,
"OpenStreetMap": osmLayer
};
var overlays = {
"<span id=\"cuencaOverlay\">Agua en la cuenca del Grijalva</span>": timeLayer
};
layerControl = L.control.layers(baseLayers, overlays).addTo(map);
makeBaseMap(); // basemap.js
});
}
const updateMap = (mapData) => {
//console.log(userFiles);
// clear tiles
currentTiles = {};
//retrieve or create tiles for current dates
userFiles.forEach( monthYear => {
if (Object.keys(allTiles).includes(monthYear)) {
currentTiles[monthYear] = allTiles[monthYear]; // recover tile if it has already been created
//currentJSONs[monthYear] = allJSONs[monthYear]; // recover json if it has already been created
return; // if file has already been processed, exit
} else { // if file cannot be found in allTiles, then add 1 to the number of files to process
let newTile = mapboxLayer(monthYear);
glmap.getMapboxMap().addLayer(newTile);
if (monthYear == userFiles[0]) {
glmap.getMapboxMap().setPaintProperty(monthYear, "fill-opacity", 0.7)
}
}
});
// update timeDimension times
timeLayer._timeDimension.setAvailableTimes(userDates, "replace");
timeLayer._timeDimension.setCurrentTime(mapData.min);
// clear minmax indicators objects
maxIndicators = {},
minIndicators = {};
indicators.forEach( (indicator) => {
maxIndicators[indicator] = 0;
minIndicators[indicator] = 1e30;
});
// query db for new minmax values then style tiles
new Promise( resolve => {
queryFiles().then( minmax => {
minmax.map( minmaxMonth => {
indicators.forEach( (indicator) => {
minIndicators[indicator] = Math.min(minIndicators[indicator], minmaxMonth[`min${indicator}`]);
maxIndicators[indicator] = Math.max(maxIndicators[indicator], minmaxMonth[`max${indicator}`]);
});
});
resolve({"map": map, "minIndicators": minIndicators, "maxIndicators": maxIndicators});
})
}).then( values => { // once we have new minmax values, style all tiles
let option = $("#indicatorSelect").val(), // option selected from dropdrown
min = values.minIndicators,
max = values.maxIndicators;
styleTiles(option, min, max)
.then(legend.addTo(map)); // add legend control -> it updates
});
// Update charts
updateCharts();
}
const updateCharts = async () => {
$(".loader").css("display", "block");
// TODO: add mask while fetching async data
// if user has drawn polygons, update chart with data inside selection
if (drawnItems.toGeoJSON().features.length != 0) {
let allData = await getDataInSelection();
indicators.map( async indicator => {
indicatorVars[indicator].chart.data( summarizeData(allData, indicator) );
});
} else {
// otherwise use all data
let allData = await getData();
indicators.map( async indicator => {
indicatorVars[indicator].chart.data( allData[indicator]);
});
}
$(".loader").hide("fade", 750);
}
// define MVT layer for given month table and all indicators
const mapboxLayer = (monthYear) => {
const baseUrl = new URL(`/data`, window.location.href).href;
let pbfLayer = {
id: monthYear,
source: {
type: "vector",
tiles: [`${baseUrl}/${monthYear}/mvt/{z}/{x}/{y}?geom_column=geom&columns=${indicators.join()}`],
maxzoom: 19,
minzoom: 6
},
"source-layer": monthYear,
type: "fill",
"paint": {
"fill-opacity": 0,
/*"fill-color": [
"interpolate",
["linear"],
["get", "df"],
1, "rgba(255, 0, 0, 0.5)", // red
1.3, "rgba(0, 255, 0, 0.5)", // green
]/*,
"fill-outline-color": [
"interpolate",
["linear"],
["get", "df"],
1, "rgba(255, 0, 0, 0.6)", // red
1.3, "rgba(0, 255, 0, 0.6)", // green
]*/
}
}
currentTiles[monthYear] = pbfLayer;
allTiles[monthYear] = pbfLayer;
return pbfLayer;
}
const setupTimeDimensionControl = () => {
L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({
_getDisplayDateFormat: date => {
let d = new Date(date);
let year = d.getFullYear().toString();
let month = d.getUTCMonth();
return `${monthArray[month]} ${year}`;
}
});
timeDimensionControl = new L.Control.TimeDimensionCustom({
loopButton: true,
/*minSpeed: 1,
maxSpeed: 5,*/
timeSteps: 1,
playReverseButton: true,
//limitSliders: true,
playerOptions: {
//buffer: 5,
//minBufferReady: 5,
transitionTime: 125,
loop: true
},
timeZones: ["Local"]
});
}
L.TimeDimension.Layer.Tile = L.TimeDimension.Layer.extend({
_setAvailableTimes: function () {
if (this.options.times) {
return L.TimeDimension.Util.parseTimesExpression(this.options.times);
} else if (this.options.timeInterval) {
let tiArray = L.TimeDimension.Util.parseTimeInterval(this.options.timeInterval);
let period = this.options.period || "P1D";
let validTimeRange = this.options.validTimeRange || undefined;
//alert("times");
return L.TimeDimension.Util.explodeTimeRange(tiArray[0], tiArray[1], period, validTimeRange);
} else {
return [];
}
},
onAdd: function (map) {
// Don't call prototype so this_update() does not get called twice
//L.TimeDimension.Layer.prototype.onAdd.call(this, map);
this._map = map;
if (!this._timeDimension && map.timeDimension) {
this._timeDimension = map.timeDimension;
}
this._timeDimension.on("timeloading", this._onNewTimeLoading, this);
this._timeDimension.on("timeload", this._update, this);
this._timeDimension.registerSyncedLayer(this);
map.addLayer(this._baseLayer);
this._update();
},
onRemove: function (map) {
this._timeDimension.unregisterSyncedLayer(this);
this._timeDimension.off("timeloading", this._onNewTimeLoading, this);
this._timeDimension.off("timeload", this._update, this);
//this._baseLayer.getContainer().style.display = "none";
Object.keys(allTiles).forEach(layer => { // hide all tiles
glmap.getMapboxMap().setPaintProperty(layer, "fill-opacity", 0);
});
//this.eachLayer(map.removeLayer, map);
//this._map = null;
},
isReady: function (time) {
// to be implemented for each type of layer
return true;
},
_update: function () {
if (!this._baseLayer || !this._map) {
return;
}
var time = this._timeDimension.getCurrentTime();
// get data for time
let d = new Date(time),
year = d.getFullYear().toString(),
m = d.getUTCMonth(),
month = monthArray[m].toLowerCase(),
monthYear = `${month}_${year}`;
// Update title
let title = $("#title");
title.html(`<h2>Cobertura de agua en la cuenca del r&iacute;o Grijalva en ${month} de ${year}</h2>`);
// Update graphs only on timeload event
indicators.forEach( indicator => {
indicatorVars[indicator].chartData = indicatorVars[indicator].chart.data(); // get chart data
indicatorVars[indicator].chart.data(indicatorVars[indicator].chartData); // set chart data
});
//console.time("process");
//console.log("data for", monthYear);
//console.log(currentTiles)
Object.keys(allTiles).forEach(layer => {
if (layer !== monthYear) { // hide all other months
glmap.getMapboxMap().setPaintProperty(layer, "fill-opacity", 0);
} else { // except current one
glmap.getMapboxMap().setPaintProperty(layer, "fill-opacity", 0.7);
}
});
//console.timeEnd("process");
}
});
L.timeDimension.layer.Tile = (layer, options) => {
return new L.TimeDimension.Layer.Tile(layer, options);
};
// When selecting indicator from dropdown, style tiles.
$("#indicatorSelect").on("change", function() {
// style currentTiles
let option = this.value; // option selected from dropdrown
styleTiles(option, minIndicators, maxIndicators)
.then(legend.addTo(map)); // add legend control -> it updates
// FIXME: re-adding control updates its contents... why?
// Highlight plot title according to selected option
indicators.forEach( indicator => {
d3.select(indicatorVars[indicator].container).select("svg text.title").classed("active", indicator === option ? true : false);
});
});
const styleTiles = (option, minIndicators, maxIndicators) => {
// define color scale domain based on min-max values for selected indicator
let domain = [minIndicators[option], maxIndicators[option]];
//console.log(domain)
scale = chroma.scale("PuBu").padding([0.5, 0]).domain(domain).classes(5);
Object.keys(currentTiles).forEach(layer => {
let color = [
"interpolate",
["linear"],
["get", option],
minIndicators[option], scale(minIndicators[option]).hex(),
maxIndicators[option], scale(maxIndicators[option]).hex()
];
glmap.getMapboxMap().setPaintProperty(layer, "fill-color", color);
});
return Promise.resolve(scale);
}
let legend = L.control({
position: "bottomright"
});
legend.onAdd = () => {
let div = L.DomUtil.create("div", "info legend leaflet-bar");
let option = $("#indicatorSelect").val();
let optionIndex = indicators.indexOf(option);
let legendText = indicatorsUnits[optionIndex] == "" ? indicatorsNames[optionIndex] :
`${indicatorsNames[optionIndex]} (${indicatorsUnits[optionIndex]})`;
var html = `<h6>${legendText}</h6><ul>`;
let classes = scale.classes();
classes.forEach( (c, idx, array) => {
if (idx != array.length - 1) {
html += `<li><i style="background: ${scale(c).hex()}"></i>${d3.format(",.4~s")(classes[idx])} - ${d3.format(",.4~s")(classes[idx+1])}</li>`;
}
});
html += "</ul>";
div.innerHTML = html;
return div;
};
\ No newline at end of file
...@@ -149,7 +149,7 @@ ...@@ -149,7 +149,7 @@
<script type="text/javascript" src="../js/Leaflet.Sync.js"></script> <script type="text/javascript" src="../js/Leaflet.Sync.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<script type="text/javascript" src="../js/jszip.min.js"></script> <script type="text/javascript" src="../js/jszip.min.js"></script>
<script src="../js/grijalva_functions.js"></script> <script src="../js/riesgos_functions.js"></script>
<script src="../js/riesgos_basemap.js"></script> <script src="../js/riesgos_basemap.js"></script>
<script src="../js/grijalva_charts.js"></script> <script src="../js/grijalva_charts.js"></script>
......
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