Skip to content
Snippets Groups Projects
main.js 39 KiB
Newer Older
  • Learn to ignore specific revisions
  •           .attr("style", "width: 100%; height: auto; font: 10px sans-serif;");
    
            // Scales
            const x = d3.scaleBand()
              .domain(processedData.map((d) => d.week))
              .range([0, 2 * Math.PI])
              .align(0);
    
            const y = d3.scaleRadial()
              .domain([0, d3.max(processedData, (d) => d[personKey])])
              .range([innerRadius, outerRadius]);
    
            const color = d3.scaleLinear()
              .domain([0, d3.max(processedData, (d) => d[sleepKey])])
              .range(["lightblue", "darkblue"]);
    
            // Add year to the center
            const uniqueYears = [...new Set(processedData.map((d) => d.year))];
            if (uniqueYears.length === 1) {
              svg
                .append("text")
                .attr("text-anchor", "middle")
                .attr("dy", "0.35em")
                .style("font-size", "20px")
                .text(uniqueYears[0]);
            }
    
            // Bars
            // Bars
    svg.append("g")
    .selectAll("path")
    .data(processedData)
    .join("path")
    .attr("d", d3.arc()
      .innerRadius(innerRadius)
      .outerRadius((d) => d[personKey] > 0 ? y(d[personKey]) : y(20)) // Hauteur fixe (20 km) pour valeurs manquantes
      .startAngle((d) => x(d.week))
      .endAngle((d) => x(d.week) + x.bandwidth())
      .padAngle(0.02)
      .padRadius(innerRadius))
    .attr("fill", (d) => d[personKey] > 0 ? color(d[sleepKey]) : "#ccc") // Couleur grise pour valeurs manquantes
    .append("title")
    .text((d) => `${d.week}\nDistance: ${d[personKey] > 0 ? d[personKey].toFixed(2) : "N/A"}\nSleep: ${d[sleepKey] > 0 ? d[sleepKey].toFixed(2) + "h" : "N/A"}`);
    
            // Week Labels with grouped years
    svg.append("g")
    .selectAll("g")
    .data(processedData)
    .join("g")
    .attr("transform", (d) => {
      const midAngle = (x(d.week) + x.bandwidth() / 2) * 180 / Math.PI - 90;
      const radius = outerRadius + 25;
      return `
        rotate(${midAngle})
        translate(${radius},0)
      `;
    })
    .call((g) => {
      g.append("text")
        .text((d, i) => {
          // Only show the year once for the first week of each year
          if (i === 0 || d.year !== processedData[i - 1].year) {
            return `${d.year} ${d.week.split("-")[1]}`;
          }
          return `${d.week.split("-")[1]}`;
        })
        .attr("text-anchor", "middle");
    });
    // Legend
    const defs = svg.append("defs");
    const gradient = defs.append("linearGradient")
      .attr("id", "sleepGradient")
      .attr("x1", "0%")
      .attr("y1", "0%")
      .attr("x2", "100%")
      .attr("y2", "0%");
    
    gradient.append("stop").attr("offset", "0%").attr("stop-color", "lightblue");
    gradient.append("stop").attr("offset", "100%").attr("stop-color", "darkblue");
    
    const legend = svg.append("g")
      .attr("transform", `translate(${-width / 2 + 30}, ${-height / 2 + 50})`); // Position à gauche
    
    // Title
    legend.append("text")
      .attr("y", 0)
      .attr("x", 0)
      .text("Durée de sommeil")
      .attr("font-size", "12px")
      .attr("text-anchor", "start")
      .attr("font-weight", "bold");
    
    // Gradient bar
    legend.append("rect")
      .attr("x", 0)
      .attr("y", 15) // Space below the title
      .attr("width", 100) // Longer gradient for better visibility
      .attr("height", 10)
      .style("fill", "url(#sleepGradient)");
    
    // Min and Max values for sleep
    legend.append("text")
      .attr("x", -5) // Align with start of gradient
      .attr("y", 35)
      .text(`${d3.min(processedData, (d) => d[sleepKey]).toFixed(1)}h`)
      .attr("font-size", "10px")
      .attr("text-anchor", "start");
    
    legend.append("text")
      .attr("x", 105) // Align with end of gradient
      .attr("y", 35)
      .text(`${d3.max(processedData, (d) => d[sleepKey]).toFixed(1)}h`)
      .attr("font-size", "10px")
      .attr("text-anchor", "start");
    
    // Gray bar for missing data
    legend.append("rect")
      .attr("x", 0)
      .attr("y", 50) // Space below the gradient
      .attr("width", 100) // Same width as gradient for consistency
      .attr("height", 10)
      .style("fill", "#ccc");
    
    // Label for gray bar
    legend.append("text")
      .attr("x", 0) // Align with start of gray bar
      .attr("y", 70) // Space below the gray bar
      .text("Valeur manquante")
      .attr("font-size", "10px")
      .attr("text-anchor", "start");
    
    
            // Add radial distance circles
    const distanceTicks = y.ticks(5); // Nombre de cercles (5 niveaux ici)
    const circleGroup = svg.append("g")
      .attr("class", "distance-circles");
    
    // Dessiner les cercles
    circleGroup.selectAll("circle")
      .data(distanceTicks)
      .join("circle")
      .attr("r", (d) => y(d))
      .attr("fill", "none")
      .attr("stroke", "#ccc")
      .attr("stroke-dasharray", "4 2"); // Ligne pointillée (facultatif)
    
    // Ajouter les étiquettes pour les distances
    circleGroup.selectAll("text")
      .data(distanceTicks)
      .join("text")
      .attr("x", 0)
      .attr("y", (d) => -y(d)) // Positionné au-dessus des cercles
      .attr("dy", "-0.3em")
      .attr("text-anchor", "middle")
      .attr("font-size", "10px")
      .text((d) => `${d.toFixed(0)} km`); // Format pour afficher les valeurs
          }
        })
        .catch((error) => console.error("Error loading data:", error));
    
        function getISOWeekNumber(date) {
          const tempDate = new Date(date);
          tempDate.setDate(tempDate.getDate() + 4 - (tempDate.getDay() || 7));
          const yearStart = new Date(tempDate.getFullYear(), 0, 1);
          return Math.ceil(((tempDate - yearStart) / 86400000 + 1) / 7);
        }
    
    }
    
    
    
    document.addEventListener("DOMContentLoaded", function () {
      renderStepsVisualization();
      renderDistanceVisualization();
      renderCaloriesVisualization();
    
      renderSleepVisualization();
    
      renderSleepActivityVisualization();
      renderRadialDistanceChart()