Skip to content
Snippets Groups Projects
elMapa.js 10.5 KiB
Newer Older
jorvill's avatar
jorvill committed
/*******************************
 ** By: Jorge Villanueva Sanz **
 *******************************/
/**
 * Referencias utilizadas
jorvill's avatar
jorvill committed
 *  Proyectos similares
 *  https://gitlab.inf.uva.es/desi_22-23/icendiossequia
jorvill's avatar
jorvill committed
 * 
 *  Otras
 *  - https://d3-graph-gallery.com/graph/choropleth_hover_effect.html
 */

// Definimos area de dibujo
const WIDTH_MAP = 700;
const HEIGHT_MAP = 400;

// Paleta de colores en formato diccionario
const paleta = {
  "gasolina":   [ "rgb( 161, 161, 161)",
                  "rgb( 138, 138, 138)",
                  "rgb( 92,  92,  92)",
                  "rgb( 69,  69,  69)",
                  "rgb( 23,  23,  23)"],

   "gasoil":    [ "rgb(  44, 207, 230)",
                  "rgb(  56, 173, 190)",
                  "rgb(  52, 145, 175)",
                  "rgb(  44, 82, 156)",
                  "rgb(  36,  56,  94)"]};

// Limites de cada grupo

const GASOLINA_MIN = 161;
const GASOLINA_MEDMIN = 175;
const GASOLINA_MEDMAX = 189;
const GASOLINA_MAX = 203;

const GASOIL_MIN = 148;
const GASOIL_MEDMIN = 163;
const GASOIL_MEDMAX = 177;
const GASOIL_MAX = 192;


// La utilizamos para obtener información sobre si es la primera o la segunda pulsación sobre la misma provincia
var lastProv;


/**
 * Función principal.
 * Muestra los datos para el año y variable seleccionada
 * 
 * @param {int} year Obtenido del slider
 * @param {String} selectedVar Obtenido de la selectBox
 */
function plotCyL(mes, selectedVar){
  
  // Eliminamos todo lo que pudiera haber anteriormente
  d3.select("#mapa").selectAll("svg").remove();

  
  // Abrimos el geoJson
  d3.json(MAP_DATA).then((mapData)=>{

    var svg = d3.select("#mapa")
            .append("svg")
            .attr("width", WIDTH_MAP)
            .attr("height", HEIGHT_MAP);
              
    // Proyeccion
    var projection = d3.geoMercator();
    var geoPath = d3.geoPath(projection);
              
    // Calculo tamaño original, calculando los valores maximos y minimos de las coordenadas x e y del mapa
    var Xmax = 0;
    var Xmin = WIDTH_MAP;
    var Ymax = 0;
    var Ymin = HEIGHT_MAP;

    numPaths = mapData.features.length;
    
    mapData.features.forEach(function(data2,i)
    {
      var bordeInfX = geoPath.bounds(data2)[0][0];
      if (bordeInfX < Xmin) 
      {
        Xmin = bordeInfX;
      }

      var bordeInfY = geoPath.bounds(data2)[0][1];
      if (bordeInfY < Ymin)
      {
        Ymin = bordeInfY;
      }

      var bordeSupX = geoPath.bounds(data2)[1][0];
      if (bordeSupX > Xmax) 
      {
        Xmax = bordeSupX;
      }

      var bordeSupY = geoPath.bounds(data2)[1][1];
      if (bordeSupY > Ymax)
      {
        Ymax = bordeSupY;
      }
                
    });
              

    var porcentajeAjuste = 1.8 // se ajusta el grafico a este porcentaje de la ventana

    var proporcionX = WIDTH_MAP / (Xmax - Xmin); // se ve cuantas veces puedo aumentar en esta dimension
    var proporcionY = HEIGHT_MAP / (Ymax - Ymin); // idem para Y

    if (proporcionX < proporcionY) // ajusto al porcentaje maximo en la dimension X
    { 
      var escala = Math.floor((WIDTH_MAP*porcentajeAjuste)/(Xmax-Xmin));
    } else{  
        var escala = Math.floor((HEIGHT_MAP*porcentajeAjuste)/(Ymax-Ymin));
    }

    // Multiplicador de escala
    escala = escala*projection.scale();
    
    projection = d3.geoMercator().scale(escala);
    geoPath = d3.geoPath(projection);
              
              
              
              
    // Se calcula el centro de cada path (Provincia), y con estos el del centro del mapa,
    // ajustando este al centro del elemento svg
              
    var centroX = 0;
    var centroY = 0;
    var numPaths = mapData.features.length;
    mapData.features.forEach(function(data2,i)
    {

      centroX = centroX + geoPath.centroid(data2)[0];
      centroY = centroY + geoPath.centroid(data2)[1];
    
    });

    centroX = centroX / numPaths;
    centroY = centroY / numPaths;

    
    var offsetX = projection.translate()[0];  
    var offsetY = projection.translate()[1];
      
    var transX = Math.floor((WIDTH_MAP/2)-centroX)+offsetX;
    var transY = Math.floor((HEIGHT_MAP/2)-centroY)+offsetY;
    
      
    projection = projection.translate([transX,transY]);
    geoPath = d3.geoPath(projection);
          

    d3.csv(mes).then(function(data) {
  
      data.forEach(function(data)
      {
        /*******************************
         * AÑADIMOS LOS DATOS AL JSON **
         *******************************/
        var dataProvincia = data.provincia;

        var dataGasolina = data.pvpG95;
        var dataGasoleo = data.pvpGOA;

        mapData.features.forEach(function(features)
        {

          var mapProvincia = features.properties.name;

          if (dataProvincia == mapProvincia) {
            // Añadimos los datos a cada provincia del año seleccionado
            features.properties.pvpG95    = dataGasolina;
            features.properties.pvpGOA    = dataGasoleo;


            
            // Colores
            features.properties.colorGasolina   = coloresMapa(dataGasolina, 'gasolina');
            features.properties.colorGasoil     = coloresMapa(dataGasoleo, 'gasoil');
          }


        });
        
      });

      
      //Dibujamos el mapa 
      svg.selectAll("path")
          .data(mapData.features)
          .enter()
          .append("path")
        
          // ATRIBUTOS
          .attr("d", geoPath)
          .attr("provincia",  function (d) { return d.properties.provincia;  })
          .attr("pvpG95",   function (d) { return d.properties.pvpG95;   })
          .attr("pvpGOA",     function (d) { return d.properties.pvpGOA;     })

          // STYLE
          .style("opacity", 0.95)
          .style("stroke", "gold")
          .style("fill", function(d) {
                // Pintamos la variable seleccionada
                var valor;

                switch(selectedVar)
                {
                  case 'gasolina':
                    valor = d.properties.pvpG95;
                    if (valor) {  return d.properties.colorGasolina; } else { return "#FFF" /*No hay datos*/; }
                  case 'gasoil':
                    valor = d.properties.pvpGOA;
                    if (valor) {  return d.properties.colorGasoil; } else { return "#FFF" /*No hay datos*/; }
                
                  }

              })

          // EVENTS
          .on("click", function(d, prov){muestraLineChart(prov);})
          .on("mousemove", handlerMouseOver)
          .on("mouseout", handlerMouseOut);
    });


          
  })
};    


/**
 * Devuelve el color de la categoría del valor introducido según el indicador
 * 
 * @param {int} valor 
 * @param {Sring} indicador 
 * @returns 
 */
function coloresMapa(valor, indicador)
{

    var color;

    console.log("Color")
    console.log(indicador)

    switch(indicador)
    {
      case 'gasolina':
        color = paleta['gasolina'];

        console.log(valor)

        if(valor < GASOLINA_MIN ){ colorDato = color[0]}
        else if (valor >= GASOLINA_MIN  && valor < GASOLINA_MEDMIN ){ colorDato = color[1]}
        else if (valor >= GASOLINA_MEDMIN && valor < GASOLINA_MEDMAX  ){ colorDato= color[2]}
        else if (valor >= GASOLINA_MEDMAX && valor < GASOLINA_MAX  ){ colorDato= color[3]}
        else if (valor > GASOLINA_MAX  ){ colorDato= color[4]}

      break;
      
      case 'gasoil':
        color = paleta['gasoil'];

        console.log(valor)

        if(valor < GASOIL_MIN ){ colorDato = color[0]}
        else if (valor >= GASOIL_MIN  && valor < GASOIL_MEDMIN ){ colorDato = color[1]}
        else if (valor >= GASOIL_MEDMIN && valor < GASOIL_MEDMAX  ){ colorDato= color[2]}
        else if (valor >= GASOIL_MEDMAX && valor < GASOIL_MAX  ){ colorDato= color[3]}
        else if (valor > GASOIL_MAX  ){ colorDato= color[4]}

      break;

    }
    
  return colorDato;
};




/**
 * Manejador del ratón cuando se sitúa sobre una provincia.
 * Muestra la información resumida y resalta la provincia en cuestión.
 * 
 */
function handlerMouseOver()
{
        
  // borramos lo que pudiera haber en la etiqueta
  document.getElementById("infoResumen").innerHTML="";

  // Resalta la provincia seleccionada
  d3.selectAll("path").style("opacity", .1);
  d3.select(this).style("opacity", 1);

  // Obtenemos la posición del ratón
  function position(event)
  {
    var x = event.clientX;
    var y = event.clientY;
    return{x,y}
  }

  
  // posRaton contiene las coordenadas {x, y} de la posicion del ratón en la pantalla
  posRaton = position(event);

  // colocamos la etiqueta en la posicion relativa al raton que queremos
  posRaton.x = posRaton.x - 205;
  posRaton.y = posRaton.y - 95;

  // modificamos la posicion del div que contiene la etiqueta para que aparezca donde hemos establecido
  d3.select("#infoResumen")
                          .style("display","block") // cambiamos la visibilidad del div que inicialmente estaba oculto
                          .style("left", posRaton.x+"px")
                          .style("top" ,posRaton.y+"px");

  // creamos un elemento svg para representar la etiqueta mediante un rectangulo con borde al que introducimos texto
  var svg = d3.select("#infoResumen")
                                    .append("svg")
                                    .attr("width", 200)
                                    .attr("height", 90);

  var etiqueta = svg.append("g");

  // Obtenemos los datos que vamos a mostrar
  
  var provincia = this.__data__.properties.name;
  var g95 = this.__data__.properties.pvpG95;
  var goa = this.__data__.properties.pvpGOA;
            
  // Nombre de la provincia
  etiqueta.append("text")
                        .style("font-size", "15px")
                        .style("font-weight", "bold")
                        .attr("x", 10)
                        .attr("y", 20)
                        .text(provincia);

  // Precio gasolina  
  etiqueta.append("text")
                        .style("font-size", "15px")
                        .attr("x", 10)
                        .attr("y", 40)
                        .text("Gasolina 95: "+g95);

  // Precio gasoil
  etiqueta.append("text")
                        .style("font-size", "15px")
                        .attr("x", 10)
                        .attr("y", 60)
                        .text("Gasóleo A: "+goa);
}

/**
 * Devuelve el mapa a la situación normal
 * 
 */
function handlerMouseOut()
{
  // Volvemos recuperar la misma tonalidad
  d3.selectAll("path").style("opacity", 1);

  // Vaciamos el contenido del div donde hemos creado la etiqueta y lo ocultamos
  document.getElementById("infoResumen").innerHTML="";
  d3.select("#infoResumen").style("display","none");

}