From fca58ebe743d1e8b5c1df67b569d4f599578b95d Mon Sep 17 00:00:00 2001 From: Pablo Martin <pablo.martin.benito@estudiantes.uva.es> Date: Fri, 6 Dec 2024 14:15:53 +0100 Subject: [PATCH] port -> paquetes, radar chart, etc --- data/data.json | 10 + .../clasificacion/clasificacion.css | 38 +-- .../clasificacion/clasificacion.html | 4 +- .../clasificacion/clasificacion.js | 6 +- src/equipo/equipo.css | 258 ++++++++++++++++++ src/equipo/equipo.html | 53 ++++ src/equipo/equipo.js | 75 +++++ ui/radarChart.js | 190 +++++++++++++ 8 files changed, 609 insertions(+), 25 deletions(-) create mode 100644 data/data.json rename practica.css => src/clasificacion/clasificacion.css (85%) rename clasificacion.html => src/clasificacion/clasificacion.html (93%) rename clasificacion.js => src/clasificacion/clasificacion.js (92%) create mode 100644 src/equipo/equipo.css create mode 100644 src/equipo/equipo.html create mode 100644 src/equipo/equipo.js create mode 100644 ui/radarChart.js diff --git a/data/data.json b/data/data.json new file mode 100644 index 0000000..80f16cc --- /dev/null +++ b/data/data.json @@ -0,0 +1,10 @@ +[ + [ + {"area": "Central ", "value": 80}, + {"area": "Kirkdale", "value": 40}, + {"area": "Kensington ", "value": 40}, + {"area": "Everton ", "value": 90}, + {"area": "Picton ", "value": 60}, + {"area": "Riverside ", "value": 80} + ] + ] \ No newline at end of file diff --git a/practica.css b/src/clasificacion/clasificacion.css similarity index 85% rename from practica.css rename to src/clasificacion/clasificacion.css index 97d421c..0d9b8d2 100644 --- a/practica.css +++ b/src/clasificacion/clasificacion.css @@ -1,7 +1,7 @@ body { margin: 0; padding: 0; - height: 100vh; + height: 1000px; display: flex; flex-direction: column; } @@ -14,8 +14,8 @@ body { @font-face { font-family: 'PremierSans'; - src: url('fonts/Premier Sans.otf') format('opentype'), - url('fonts/Premier Sans.ttf') format('truetype'); + src: url('/fonts/Premier Sans.otf') format('opentype'), + url('/fonts/Premier Sans.ttf') format('truetype'); font-weight: normal; font-style: normal; } @@ -30,10 +30,10 @@ body { h1 { color: white; - font-size: 100px; + font-size: 80px; margin-bottom: 10px; margin-top: 0; - padding-top: 20px; + padding-top: 30px; } h4 { @@ -46,7 +46,7 @@ h4 { h3 { font-family: "Bebas Neue"; color: #00FF85; - font-size: 50px; + font-size: 40px; margin-top: 20px; margin-bottom: 10px; padding-left: 30px; @@ -60,7 +60,7 @@ h3 { background-color: #38003C; padding-top: 30px; padding-bottom: 30px; - width: 300px; + width: 200px; height: 100%; } @@ -83,7 +83,7 @@ h3 { } .content { display: flex; - height: 100%; + height: 90%; margin-top: 0; } @@ -102,35 +102,34 @@ h3 { .headerTable { background-color: #38003C; color: white; - font-size: 40px; + font-size: 30px; text-align: justify; display: flex; justify-content: space-between; - margin-top: 40px; - margin-left: 100px; - margin-right: 100px; + margin-top: 25px; + margin-left: 200px; + margin-right: 200px; border-radius: 30px; } #tableTitle{ margin-left: 100px; - padding-top: 10px; - font-family: "Bebas Neue"; - font-size: 50px; + font-family: "PremierSans"; + font-size: 40px; } #season { margin-right: 50px; - margin-top: 50px; + margin-top: 40px; font-family: "PremierSans", Arial, Helvetica Neue, Helvetica, sans-serif; - font-size: 60px; + font-size: 35px; } #seasonNumber { - margin-top: 40px; + margin-top: 30px; margin-right: 100px; - font-size: 80px; + font-size: 50px; font-family: "PremierSans", Arial, Helvetica Neue, Helvetica, sans-serif; } @@ -143,6 +142,7 @@ h3 { justify-content: center; align-items: flex-start; height: 100%; + } diff --git a/clasificacion.html b/src/clasificacion/clasificacion.html similarity index 93% rename from clasificacion.html rename to src/clasificacion/clasificacion.html index a0fff7d..4a044c7 100644 --- a/clasificacion.html +++ b/src/clasificacion/clasificacion.html @@ -5,9 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Reparto Puntos PremierLeague</title> <!-- CSS --> - <link rel="stylesheet" href="practica.css"> - <!-- JavaScript --> - <script src="practica.js"></script> + <link rel="stylesheet" href="clasificacion.css"> <!-- fuente bebas neue --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> diff --git a/clasificacion.js b/src/clasificacion/clasificacion.js similarity index 92% rename from clasificacion.js rename to src/clasificacion/clasificacion.js index b66e0f7..b24d65d 100644 --- a/clasificacion.js +++ b/src/clasificacion/clasificacion.js @@ -19,7 +19,7 @@ document.addEventListener('DOMContentLoaded', function() { var selectedSeason = 2024; - d3.csv("data/premier-tables.csv").then(function(data){ + d3.csv("/data/premier-tables.csv").then(function(data){ data.forEach(function(d) { d.points = +d.points; }); @@ -41,8 +41,8 @@ document.addEventListener('DOMContentLoaded', function() { .call(yAxis) .selectAll("text") .style("text-anchor", "end") - .style("font-size", "30px") - .style("font-family", "PremierSans") + .style("font-size", "20px") + .style("font-family", "aptos") .attr("dx", "-.5em") svg.selectAll(".bar") diff --git a/src/equipo/equipo.css b/src/equipo/equipo.css new file mode 100644 index 0000000..daaa95d --- /dev/null +++ b/src/equipo/equipo.css @@ -0,0 +1,258 @@ +body { + margin: 0; + padding: 0; + height: 1000px; + display: flex; + flex-direction: column; +} + +.bebas-neue-regular { + font-family: "Bebas Neue", serif; + font-weight: 400; + font-style: normal; + } + + @font-face { + font-family: 'PremierSans'; + src: url('fonts/Premier Sans.otf') format('opentype'), + url('fonts/Premier Sans.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +.header{ + font-family: "Bebas Neue"; + text-align: center; + background-color: #38003C; + margin-bottom: 0px; + height: 20%; + } + +h1 { + color: white; + font-size: 80px; + margin-bottom: 10px; + margin-top: 0; + padding-top: 30px; +} + +h4 { + color: #00FF85; + font-size: 25px; + margin-top: 10px; + padding-bottom: 30px; +} + +h3 { + font-family: "Bebas Neue"; + color: #00FF85; + font-size: 40px; + margin-top: 20px; + margin-bottom: 10px; + padding-left: 30px; +} + +.sideNav { + border-top: solid 3px grey; + border-right: solid 5px #00FF85; + border-bottom: solid 5px #00FF85; + border-bottom-right-radius: 30px; + background-color: #38003C; + padding-top: 30px; + padding-bottom: 30px; + width: 200px; + height: 100%; +} + +.navButton { + display: block; + padding: 10px 20px; + color: white; + background-color: #38003C; + border: none; + text-align: center; + width: 100%; + font-size: 25px; + cursor: pointer; + font-family: "Bebas Neue"; +} + +.navButton:hover { + background-color: #00FF85; + color: black; +} +.content { + display: flex; + height: 90%; + margin-top: 0; +} + +.mainContent{ + width: 100%; + height: 100%; +} + +.table { + width: 100%; + height: 100%; + border-collapse: collapse; + margin-top: 20px; +} + +.headerTable { + background-color: #38003C; + color: white; + font-size: 40px; + text-align: justify; + display: flex; + justify-content: space-between; + margin-top: 40px; + margin-left: 100px; + margin-right: 100px; + border-radius: 30px; +} + + +#tableTitle{ + margin-left: 100px; + padding-top: 10px; + font-family: "Bebas Neue"; + font-size: 50px; +} + +#season { + margin-right: 50px; + margin-top: 50px; + font-family: "PremierSans", Arial, Helvetica Neue, Helvetica, sans-serif; + font-size: 60px; +} + +#seasonNumber { + margin-top: 40px; + margin-right: 100px; + font-size: 80px; + font-family: "PremierSans", Arial, Helvetica Neue, Helvetica, sans-serif; +} + +.seasonInfo{ + display: flex; +} + +#graph { + display: flex; + justify-content: center; + align-items: flex-start; + height: 100%; + border: solid 3px black; +} + + + +.bar { + fill: steelblue; + +} + +.bar:hover { + fill: red; +} +.axis text { + font: 20px sans-serif; +} + +.axis path, +.axis line { + fill: none; + shape-rendering: crispEdges; +} + + +/* equipo.html */ +.subHeader { + display: flex; + align-items: center; + margin-top: 10px; + margin-left: auto; + margin-right: auto; + border-radius: 30px; + width: 70%; /* Ajusta el ancho según sea necesario */ + +} + +#subHeaderTitle { + font-family: "Bebas Neue"; + color: #38003C; + font-size: 40px; + padding-right: 70px; + padding-left: 30px; + padding-top: 30px; + padding-bottom: 30px; + border-right: solid 3px grey; +} + +label { + font-family: "aptos"; + font-size: 18px; + color: #38003C; + margin-left: 10px; + margin-bottom: 10px; +} + +.inputs { + margin-left: 80px; + display: flex; + flex-direction: column; +} + +input, select { + font-family: "aptos"; + font-size: 20px; + padding: 15px; + border-radius: 20px; + border: solid 2px #38003C; +} + +select:hover, input:hover { + border-color: #00FF85; +} + +option { + font-family: "aptos"; + font-size: 18px; + color: #38003C; + background-color: white; +} + + + +#graphContainer { + display: flex; + align-items: flex-start; + height: 80%; + border: solid 3px black; + border-radius: 20px; + + margin-left: 100px; + margin-right: 100px; +} + +#teamTitle { + font-family: "Bebas Neue"; + color: black; + font-size: 50px; + padding-right: 50px; + + border-right: solid 3px grey; + margin-top: 60px; + margin-left: 80px; + +} + +#graph2 { + display: flex; + justify-content: center; + align-items: flex-start; + height: 100%; + width: 100%; +} + diff --git a/src/equipo/equipo.html b/src/equipo/equipo.html new file mode 100644 index 0000000..915c98a --- /dev/null +++ b/src/equipo/equipo.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Reparto Puntos PremierLeague</title> + <!-- CSS --> + <link rel="stylesheet" href="equipo.css"> + <!-- fuente bebas neue --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap" rel="stylesheet"> + <!-- D3 --> + <script src="https://d3js.org/d3.v7.min.js"></script> + <script src="equipo.js" defer></script> + <script src="/ui/radarChart.js" defer></script> + +</head> +<body> + <div class="header"> + <h1>Clasificaciones premier league</h1> + <h4>PABLO MARTÃN DE BENITO</h4> + </div> + + <div class="content"> + <div class="sideNav"> + <h3>Menu</h4> + <button class="navButton">Clasificacion</button> + <button class="navButton">Equipo</button> + </div> + <div class="mainContent"> + <div class="subHeader"> + <h2 id="subHeaderTitle">stats Equipo</h2> + <div class="inputs"> + <label for="seasonInput">Temporada (Año de fin)</label> + <input type="text" id="seasonInput" name="season" value="2024" oninput="onChangeSeason()"> + </div> + <div class="inputs"> + <label for="teamSelect">Equipo</label> + <select id="teamSelect" name="team" > + </select> + </div> + </div> + <div id="graphContainer"> + <h2 id="teamTitle"></h2> + <div id="graph2"> + </div> + </div> + </div> + </div> + +</body> +</html> \ No newline at end of file diff --git a/src/equipo/equipo.js b/src/equipo/equipo.js new file mode 100644 index 0000000..ef8ec92 --- /dev/null +++ b/src/equipo/equipo.js @@ -0,0 +1,75 @@ +document.addEventListener('DOMContentLoaded', function() { + var margin = {top: 70, right: 20, bottom: 30, left: 200}, + w = 800 - margin.left - margin.right, + h = 800 - margin.top - margin.bottom; + + + + ////////////////////////////////////////////////////////////////////////// + + // Manejador para evento de cambio de temporada + // Actualiza el select de equipos + function onChangeSeason() { + var selectedSeason = document.getElementById("seasonInput").value; + + d3.csv("/data/premier-tables.csv").then(function(data) { + data.forEach(function(d) { + d.points = +d.points; + }); + + // Filtra los datos según la temporada seleccionada + var filteredData = data.filter(function(d) { + return d.season_end_year == selectedSeason; + }); + + // Actualiza el select con los equipos + var teamSelect = document.getElementById("teamSelect"); + teamSelect.innerHTML = '<option value="" disabled selected>Seleccione un equipo</option>'; // Clear existing options and add default + + + filteredData.forEach(function(d) { + var option = document.createElement('option'); + option.value = d.team; + option.textContent = d.team; + teamSelect.appendChild(option); + }); + }); + } + + // Manejador para evento de cambio de equipo del select + function onChangeTeam() { + document.getElementById("teamTitle").textContent = document.getElementById("teamSelect").value; + + var data = [ + [ + {axis: "strength", value: 80}, + {axis: "intelligence", value: 6}, + {axis: "charisma", value: 5}, + {axis: "dexterity", value: 9}, + {axis: "luck", value: 2} + ] + ]; + + var config = { + w: w, + h: h, + maxValue: 100, + levels: 5, + ExtraWidthX: 300 + } + + RadarChart.draw("#graph2", data, config); + } + + // Inicializa la página con los datos por defecto + function init() { + onChangeSeason(); + } + + + init(); + // Eventos + document.getElementById("seasonInput").addEventListener('input', onChangeSeason); + document.getElementById("teamSelect").addEventListener('input', onChangeTeam); +}); + diff --git a/ui/radarChart.js b/ui/radarChart.js new file mode 100644 index 0000000..0822cf3 --- /dev/null +++ b/ui/radarChart.js @@ -0,0 +1,190 @@ +var RadarChart = { + draw: function(id, d, options){ + var cfg = { + radius: 5, + w: 600, + h: 600, + factor: 1, + factorLegend: .85, + levels: 3, + maxValue: 0, + radians: 2 * Math.PI, + opacityArea: 0.5, + ToRight: 5, + TranslateX: 80, + TranslateY: 30, + ExtraWidthX: 100, + ExtraWidthY: 100, + color: d3.scaleOrdinal().range(["#6F257F", "#CA0D59"]) + }; + + if('undefined' !== typeof options){ + for(var i in options){ + if('undefined' !== typeof options[i]){ + cfg[i] = options[i]; + } + } + } + + cfg.maxValue = 100; + + var allAxis = (d[0].map(function(i, j){return i.area})); + var total = allAxis.length; + var radius = cfg.factor*Math.min(cfg.w/2, cfg.h/2); + var Format = d3.format('%'); + d3.select(id).select("svg").remove(); + + var g = d3.select(id) + .append("svg") + .attr("width", cfg.w+cfg.ExtraWidthX) + .attr("height", cfg.h+cfg.ExtraWidthY) + .append("g") + .attr("transform", "translate(" + cfg.TranslateX + "," + cfg.TranslateY + ")"); + + var tooltip; + + //Circular segments + for(var j=0; j<cfg.levels; j++){ + var levelFactor = cfg.factor*radius*((j+1)/cfg.levels); + g.selectAll(".levels") + .data(allAxis) + .enter() + .append("svg:line") + .attr("x1", function(d, i){return levelFactor*(1-cfg.factor*Math.sin(i*cfg.radians/total));}) + .attr("y1", function(d, i){return levelFactor*(1-cfg.factor*Math.cos(i*cfg.radians/total));}) + .attr("x2", function(d, i){return levelFactor*(1-cfg.factor*Math.sin((i+1)*cfg.radians/total));}) + .attr("y2", function(d, i){return levelFactor*(1-cfg.factor*Math.cos((i+1)*cfg.radians/total));}) + .attr("class", "line") + .style("stroke", "grey") + .style("stroke-opacity", "0.75") + .style("stroke-width", "0.3px") + .attr("transform", "translate(" + (cfg.w/2-levelFactor) + ", " + (cfg.h/2-levelFactor) + ")"); + } + + //Text indicating at what % each level is + for(var j=0; j<cfg.levels; j++){ + var levelFactor = cfg.factor*radius*((j+1)/cfg.levels); + g.selectAll(".levels") + .data([1]) //dummy data + .enter() + .append("svg:text") + .attr("x", function(d){return levelFactor*(1-cfg.factor*Math.sin(0));}) + .attr("y", function(d){return levelFactor*(1-cfg.factor*Math.cos(0));}) + .attr("class", "legend") + .style("font-family", "sans-serif") + .style("font-size", "10px") + .attr("transform", "translate(" + (cfg.w/2-levelFactor + cfg.ToRight) + ", " + (cfg.h/2-levelFactor) + ")") + .attr("fill", "#737373") + .text((j+1)*100/cfg.levels); + } + + series = 0; + + var axis = g.selectAll(".axis") + .data(allAxis) + .enter() + .append("g") + .attr("class", "axis"); + + axis.append("line") + .attr("x1", cfg.w/2) + .attr("y1", cfg.h/2) + .attr("x2", function(d, i){return cfg.w/2*(1-cfg.factor*Math.sin(i*cfg.radians/total));}) + .attr("y2", function(d, i){return cfg.h/2*(1-cfg.factor*Math.cos(i*cfg.radians/total));}) + .attr("class", "line") + .style("stroke", "grey") + .style("stroke-width", "1px"); + + axis.append("text") + .attr("class", "legend") + .text(function(d){return d}) + .style("font-family", "sans-serif") + .style("font-size", "11px") + .attr("text-anchor", "middle") + .attr("dy", "1.5em") + .attr("transform", function(d, i){return "translate(0, -10)"}) + .attr("x", function(d, i){return cfg.w/2*(1-cfg.factorLegend*Math.sin(i*cfg.radians/total))-60*Math.sin(i*cfg.radians/total);}) + .attr("y", function(d, i){return cfg.h/2*(1-Math.cos(i*cfg.radians/total))-20*Math.cos(i*cfg.radians/total);}); + + + d.forEach(function(y, x){ + dataValues = []; + g.selectAll(".nodes") + .data(y, function(j, i){ + dataValues.push([ + cfg.w/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.sin(i*cfg.radians/total)), + cfg.h/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.cos(i*cfg.radians/total)) + ]); + }); + dataValues.push(dataValues[0]); + g.selectAll(".area") + .data([dataValues]) + .enter() + .append("polygon") + .attr("class", "radar-chart-serie"+series) + .style("stroke-width", "2px") + .style("stroke", cfg.color(series)) + .attr("points",function(d) { + var str=""; + for(var pti=0;pti<d.length;pti++){ + str=str+d[pti][0]+","+d[pti][1]+" "; + } + return str; + }) + .style("fill", function(j, i){return cfg.color(series)}) + .style("fill-opacity", cfg.opacityArea) + .on('mouseover', function (d){ + z = "polygon."+d3.select(this).attr("class"); + g.selectAll("polygon") + .transition(200) + .style("fill-opacity", 0.1); + g.selectAll(z) + .transition(200) + .style("fill-opacity", .7); + }) + .on('mouseout', function(){ + g.selectAll("polygon") + .transition(200) + .style("fill-opacity", cfg.opacityArea); + }); + series++; + }); + series=0; + + + var tooltip = d3.select("body").append("div").attr("class", "toolTip"); + d.forEach(function(y, x){ + g.selectAll(".nodes") + .data(y).enter() + .append("svg:circle") + .attr("class", "radar-chart-serie"+series) + .attr('r', cfg.radius) + .attr("alt", function(j){return Math.max(j.value, 0)}) + .attr("cx", function(j, i){ + dataValues.push([ + cfg.w/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.sin(i*cfg.radians/total)), + cfg.h/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.cos(i*cfg.radians/total)) + ]); + return cfg.w/2*(1-(Math.max(j.value, 0)/cfg.maxValue)*cfg.factor*Math.sin(i*cfg.radians/total)); + }) + .attr("cy", function(j, i){ + return cfg.h/2*(1-(Math.max(j.value, 0)/cfg.maxValue)*cfg.factor*Math.cos(i*cfg.radians/total)); + }) + .attr("data-id", function(j){return j.area}) + .style("fill", "#fff") + .style("stroke-width", "2px") + .style("stroke", cfg.color(series)).style("fill-opacity", .9) + .on('mouseover', function (d){ + console.log(d.area) + tooltip + .style("left", d3.event.pageX - 40 + "px") + .style("top", d3.event.pageY - 80 + "px") + .style("display", "inline-block") + .html((d.area) + "<br><span>" + (d.value) + "</span>"); + }) + .on("mouseout", function(d){ tooltip.style("display", "none");}); + + series++; + }); + } + }; \ No newline at end of file -- GitLab