Skip to content
Snippets Groups Projects
Select Git revision
1 result Searching

FranceMap.jsx

Blame
  • FranceMap.jsx 4.87 KiB
    import { useEffect, useState, useRef } from "react";
    import PropTypes from "prop-types";
    import axios from "axios";
    import * as d3 from "d3";
    
    const FranceMap = ({ typeIndic = "indicateurs" }) => {
    
      if (typeof typeIndic !== "string") {
        console.error("typeIndic doit être une chaîne de caractères, reçu :", typeIndic);
        typeIndic = "indicateurs"; // Valeur par défaut
      }
    
      console.log("typeIndic reçu :", typeIndic);
    
      const [geoData, setGeoData] = useState(null);
      const [deptColors, setDeptColors] = useState({});
      const [deptAverages, setDeptAverages] = useState({});
      const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
      const [selectedDept, setSelectedDept] = useState(null);
      const svgRef = useRef();
      const containerRef = useRef();
    
      // Charger les données GeoJSON
      useEffect(() => {
        console.log("url : ", "http://localhost:5000/api/" + typeIndic);
        axios
          .get("/France_dep.geojson")
          .then((res) => {
            setGeoData(res.data.features);
          })
          .catch((err) => console.error("Erreur lors du chargement du GeoJSON :", err));
    
        // Charger les couleurs depuis l'API backend
        axios.get("http://localhost:5000/api/" + typeIndic)
        .then((res) => {
          console.log("Couleurs reçues du backend :", res.data.colors);
          setDeptColors(res.data.colors);
          console.log("Moyennes reçues du backend :", res.data.averages);
          setDeptAverages(res.data.averages);
          
        })
        .catch((err) => console.error("Erreur lors du chargement des couleurs :", err));
      }, [typeIndic]);
    
      // Calculer la taille du conteneur parent et mettre à jour les dimensions
      useEffect(() => {
        const updateDimensions = () => {
          const { clientWidth, clientHeight } = containerRef.current;
          setDimensions({
            width: clientWidth * 0.75,
            height: clientHeight * 0.75,
          });
        };
    
        updateDimensions();
        window.addEventListener("resize", updateDimensions);
        return () => window.removeEventListener("resize", updateDimensions);
      }, []);
    
      // Mettre à jour la carte avec les nouvelles dimensions et couleurs
      useEffect(() => {
        if (!geoData || dimensions.width === 0 || dimensions.height === 0) return;
    
        const svg = d3.select(svgRef.current)
          .attr("width", dimensions.width)
          .attr("height", dimensions.height);
    
        const projection = d3.geoMercator()
          .fitSize([dimensions.width, dimensions.height], { type: "FeatureCollection", features: geoData });
    
        const pathGenerator = d3.geoPath().projection(projection);
    
        const tooltip = d3.select("#tooltip");
    
        svg.selectAll("path")
          .data(geoData)
          .join("path")
          .attr("d", pathGenerator)
          .attr("stroke", "black")
          .attr("fill", d => deptColors[d.properties.code] || "lightgray")
          .attr("opacity", 0.8)
          
          .on("click", function (event, d) {
            if (d && d.properties) {
              console.log(`Département sélectionné : ${d.properties.nom} (${d.properties.code})`);
              setSelectedDept(d);
            } else {
              console.error("Données du département manquantes ou mal formatées", d);
            }
          })
          
    
          .on("mouseover", function (event, d) {
            // Diminuer l'opacité des autres départements (50%)
            svg.selectAll("path")
            .attr("opacity", (dept) => dept.properties.code === d.properties.code || dept === selectedDept ? 1 : 0.25);
    
            tooltip.style("display", "block")
              .html(`<strong>${d.properties.nom} (${d.properties.code})</strong><br>Score moyen : ${deptAverages[d.properties.code] || "N/A"}`)
              .style("left", event.pageX + 3 + "px")
              .style("top", event.pageY + 3 + "px");
          })
    
          .on("mousemove", function (event) {
            tooltip.style("left", event.pageX -185 + "px")
              .style("top", event.pageY -50 + "px");
          })
    
          .on("mouseout", function () {
            // Rétablir l'opacité à 100% pour tous les départements
            svg.selectAll("path")
              .attr("opacity", 1);
    
            tooltip.style("display", "none");
          })
          .attr("fill", (d) => {
            if (selectedDept && selectedDept.properties.code === d.properties.code) {
              return "red"; // Couleur pour le département sélectionné
            }
            return deptColors[d.properties.code] || "lightgray";
          });
      }, [geoData, deptColors, dimensions, selectedDept, deptAverages]);
    
      return (
        <div ref={containerRef} style={{ position: "relative", width: "100%", height: "100%", display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
          <h1 style={{ textAlign: "center", fontSize: "2em" }}>Carte de France</h1>
          <svg ref={svgRef}></svg>
          <div id="tooltip" style={{ position: "absolute", background: "white", padding: "5px", borderRadius: "5px", border: "1px solid black", display: "none" }}></div>
        </div>
      );
    };
    FranceMap.propTypes = {
      typeIndic: PropTypes.string,
    };
    
    export default FranceMap;