Skip to content
Snippets Groups Projects
Commit 64df126c authored by BOUDJEBBOUR MAYA p2312048's avatar BOUDJEBBOUR MAYA p2312048
Browse files

ajout visualisation calories-distance

parent bd05221c
No related branches found
No related tags found
No related merge requests found
...@@ -49,11 +49,6 @@ fetch('final_combined_with_all_data.json') ...@@ -49,11 +49,6 @@ fetch('final_combined_with_all_data.json')
// Initialisation de la visualisation avec l'année 2024 // Initialisation de la visualisation avec l'année 2024
updateVisualization(2024); updateVisualization(2024);
// Tooltip
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Fonction de mise à jour de la visualisation // Fonction de mise à jour de la visualisation
function updateVisualization(selectedYear) { function updateVisualization(selectedYear) {
const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString()); const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString());
...@@ -172,8 +167,6 @@ fetch('final_combined_with_all_data.json') ...@@ -172,8 +167,6 @@ fetch('final_combined_with_all_data.json')
.attr("d", area) .attr("d", area)
.attr("fill", colorScale(member)) .attr("fill", colorScale(member))
.attr("opacity", 0.8) // Opacité augmentée pour plus de visibilité .attr("opacity", 0.8) // Opacité augmentée pour plus de visibilité
//.attr("stroke", "white") // Bordure blanche
// .attr("stroke-width", 2) // Épaisseur de la bordure
}); });
} }
......
...@@ -50,11 +50,6 @@ fetch('final_combined_with_all_data.json') ...@@ -50,11 +50,6 @@ fetch('final_combined_with_all_data.json')
// Initialisation de la visualisation avec l'année 2024 // Initialisation de la visualisation avec l'année 2024
updateVisualization(2024); updateVisualization(2024);
// Tooltip
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Fonction de mise à jour de la visualisation // Fonction de mise à jour de la visualisation
function updateVisualization(selectedYear) { function updateVisualization(selectedYear) {
...@@ -177,16 +172,7 @@ fetch('final_combined_with_all_data.json') ...@@ -177,16 +172,7 @@ fetch('final_combined_with_all_data.json')
.attr("stroke", colorMap[member]) .attr("stroke", colorMap[member])
.attr("stroke-width", 2) .attr("stroke-width", 2)
.style("stroke-dasharray", isAllZero ? "5,5" : "none") // Ajouter des pointillés si toutes les données sont manquantes .style("stroke-dasharray", isAllZero ? "5,5" : "none") // Ajouter des pointillés si toutes les données sont manquantes
.on("mouseover", function(event, d) { });
tooltip.transition().duration(200).style("opacity", .9);
tooltip.html(`${member} : Nombre de pas par mois`)
.style("left", (event.pageX + 5) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition().duration(500).style("opacity", 0);
});
});
} }
// Initialisation de la visualisation avec 2024 // Initialisation de la visualisation avec 2024
......
This diff is collapsed.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Analyse de la distance parcourue</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="visualization"></div>
<div id="detail-container"></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="script.js"></script>
</body>
</html>
// Charger les données depuis le fichier JSON
fetch('final_combined_with_all_data.json')
.then((response) => response.json())
.then((data) => {
const parseDate = d3.timeParse("%Y-%m-%d");
const formatYear = d3.timeFormat("%Y");
const formatMonth = d3.timeFormat("%Y-%m");
const members = ["Corentin", "Maya", "Anis", "Amira"];
data.forEach(d => d.date = parseDate(d.date));
// Dimensions et marges
const margin = { top: 50, right: 230, bottom: 150, left: 70 };
const width = 1000 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
// Créer le conteneur SVG principal
const svg = d3.select("#visualization")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Créer un conteneur pour le graphique détaillé
const detailContainer = d3.select("#visualization")
.append("div")
.attr("id", "detail-container")
.style("margin-top", "20px");
// Définir les années et la plage d'affichage, sans 2022
const years = [2023, 2024];
// Créer le slider
const sliderContainer = d3.select("#visualization")
.append("div")
.attr("id", "slider-container")
//.style("align-items", "center")
.style("justify-content", "space-between");
const rangeSlider = sliderContainer.append("input")
.attr("type", "range")
.attr("min", 0)
.attr("max", years.length - 1)
.attr("value", years.indexOf(2024)) // Initialiser avec 2024
.style("width", "60%");
const yearDisplay = sliderContainer.append("span")
.text(years[years.indexOf(2024)]); // Afficher 2024 par défaut
// Tooltip
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Fonction de mise à jour de la visualisation
function updateVisualization(selectedYear) {
const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString());
const groupedData = d3.groups(filteredData, d => formatMonth(d.date));
const colorMap = {
"Maya": "#0f7e06",
"Corentin": "#1d38e3",
"Anis": "#d6bff4",
"Amira": "#7e09bd"
};
const aggregatedData = groupedData.map(([month, records]) => {
const aggregated = { month };
members.forEach(member => {
aggregated[`Distance_${member}`] = d3.mean(records, d => {
const distance = d[`Distance_${member}`];
return (distance !== -1) ? distance : undefined; // Exclure les valeurs de -1
}) || 0; // Si toutes les valeurs sont -1 ou manquantes, utiliser 0
aggregated[`Calories_${member}`] = d3.mean(records, d => {
const calories = d[`Calories_${member}`];
return (calories !== -1) ? calories : undefined; // Exclure les valeurs de -1
}) || 0; // Si toutes les valeurs sont -1 ou manquantes, utiliser 0
});
return aggregated;
});
svg.selectAll("*").remove();
svg.append("text")
.attr("x", width / 2) // Centrer horizontalement
.attr("y", margin.top - 60) // Positionner légèrement au-dessus du graphique
.attr("text-anchor", "middle") // Centrer le texte
.style("font-size", "16px") // Taille de police
.style("font-weight", "bold") // Gras
.text("Comparaison des calories brûlées vs distance parcourue");
// Créer une échelle pour la taille des bulles
const bubbleSizeScale = d3.scaleLinear()
.domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Distance_${member}`])) )])
.range([2, 20]); // Plage de taille réduite des bulles (2 à 20)
const xScale = d3.scaleLinear()
.domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Distance_${member}`])) )])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Calories_${member}`])) )])
.range([height, 0]);
// Axe X (Distance)
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(xScale));
svg.append("text")
.attr("x", width / 2)
.attr("y", height + 70)
.attr("text-anchor", "middle")
.style("font-size", "14px")
.text("Distance (KM)");
// Axe Y (Calories)
svg.append("g")
.call(d3.axisLeft(yScale));
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -height / 2)
.attr("y", -50)
.attr("text-anchor", "middle")
.style("font-size", "14px")
.text("Calories brûlées");
// Légende des membres (rectangles colorés)
const legend = svg.append("g")
.attr("transform", `translate(${width + 10}, 20)`);
members.forEach((member, i) => {
legend.append("rect")
.attr("x", 0)
.attr("y", i * 20)
.attr("width", 15)
.attr("height", 15)
.attr("fill", colorMap[member]);
legend.append("text")
.attr("x", 20)
.attr("y", i * 20 + 12)
.text(member)
.style("font-size", "12px")
.attr("text-anchor", "start");
});
// Bulles pour chaque membre
members.forEach((member, i) => {
svg.selectAll(`.bubble-${member}`)
.data(aggregatedData)
.enter()
.append("circle")
.attr("cx", d => xScale(d[`Distance_${member}`]))
.attr("cy", d => yScale(d[`Calories_${member}`]))
.attr("r", d => bubbleSizeScale(d[`Distance_${member}`]))
.attr("fill", d => {
// Si la distance ou les calories sont égales à 0 (valeurs manquantes ou -1), utiliser une bulle grise
return (d[`Distance_${member}`] === 0 || d[`Calories_${member}`] === 0) ? "gray" : colorMap[member];
})
.style("opacity", 0.7)
.on("mouseover", function(event, d) {
tooltip.transition().duration(200).style("opacity", .9);
tooltip.html(`Mois : ${d.month}<br>Distance : ${d[`Distance_${member}`]} km<br>Calories : ${d[`Calories_${member}`]} cal`)
.style("left", (event.pageX + 5) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition().duration(500).style("opacity", 0);
});
});
}
// Initialisation de la visualisation
updateVisualization(years[1]);
// Mettre à jour la visualisation lorsque le slider est déplacé
rangeSlider.on("input", function() {
const selectedYear = years[this.value];
yearDisplay.text(selectedYear);
updateVisualization(selectedYear);
});
})
.catch((error) => console.log(error));
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f4f4f4;
}
#visualization {
width: 60%;
height: 70vh;
margin-top: 20px;
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
}
#slider-container {
position: absolute; /* Fixe le conteneur du slider en haut */
top: 545px; /* Distance par rapport au haut de la page */
left: 25%;
background: #ffffff;
padding: 10px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
/* Tooltip Styles */
.tooltip {
position: absolute;
background-color: rgba(0, 0, 0, 0.7);
color: #fff;
padding: 8px;
border-radius: 4px;
font-size: 0.9rem;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment