Diagrama de Gantt en HTML + JavaScript + CSS
Un diagrama de Gantt es un tipo de gráfico, utilizado como herramienta a la hora de planificar proyectos.
¿Qué es un diagrama de Gantt?
Este diagrama aportará una vista general de todas las tareas y sus fechas de inicio y fin.
A mayores, en cada tarea podremos asociar personas, el % realizado de cada tarea, etc.
Aunque existen distintas plataformas online para crear y gestionar este tipo de diagramas, a continuación te dejamos un sencillo código escrito en Html, JavaScript y CSS que puede resultarte útil a la hora de desarrollar un herramienta de este tipo.
Es un ejemplo muy muy simple, en el que existe una clase de JavaScript que, a partir de un array de datos, crea y muestra una tabla HTML a modo de diagrama de Gantt.
Código HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Diagrama de Gantt</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" type="text/css" href="gantt.css">
<script type="text/javascript" src="gantt.js"></script>
</head>
<body>
<div id="gantt"></div>
<script type="text/javascript">
const obj = new Gantt([
['Action 1', '2022/05/12', '2022/05/12', '#4287f5', 80],
['Action 2', '2022/05/12', '2022/05/14', '#c1409b', 10],
['Action 3', '2022/05/14', '2022/05/17', '#0b9971', 20],
['Action 4', '2022/05/18', '2022/05/22', '#d26a52', 55],
['Action 5', '2022/05/19', '2022/05/22', '#4287f5', 100],
['Action 6', '2022/05/12', '2022/05/20', '#0b9971', 32],
]);
</script>
</body>
</html>
Código JavaScript
class Gantt {
/**
* Init representation in HTML
* @param {array} the tasks list
*
*/
constructor(tasks) {
this.tasks = tasks;
this.dateWidth = 178;
this.setMinAndMaxDate();
document.getElementById('gantt').innerHTML = this.buildTableHeader() + this.buildTableBody();
}
/**
* Get min and max dates from all tasks
*
*/
setMinAndMaxDate(){
var maxDates = [];
var minDates = [];
for(let i = 0; i < this.tasks.length; i++){
minDates.push(new Date(this.tasks[i][1]));
maxDates.push(new Date(this.tasks[i][2]));
}
this.minDate = new Date(Math.min.apply(null,minDates));
this.maxDate = new Date(Math.max.apply(null,maxDates));
}
/**
* Generate the html for the table header
* @returns {Sting} Html code
*/
buildTableHeader(){
var html = '<table><thead><tr>';
var diffDays = this.diffInDays(this.maxDate, this.minDate) + 1;
const actual = new Date(this.minDate);
for(let i = 0; i < diffDays; i++){
actual.setDate(actual.getDate() + 1);
html += '<th>'+actual.toISOString().substr(0, 10).replace('T', ' ')+"</th>";
}
html += '</tr></thead><tbody>';
return html;
}
/**
* Generate the html for the table body
* @returns {Sting} Html code
*/
buildTableBody(){
var html = '';
for(let i = 0; i < this.tasks.length; i++){
var task = this.tasks[i];
var dMin = new Date(task[1]);
var dMax = new Date(task[2]);
var days = this.diffInDays(dMax, dMin) + 1;
var daysBefore = this.diffInDays(this.minDate, dMin);
var daysAfter = this.diffInDays(dMax, this.maxDate);
if(this.minDate == dMin) daysBefore = 0;
if(this.maxDate == dMax) daysAfter = 0;
html += '<tr>';
if(daysBefore > 0) for(let j = 0; j < daysBefore; j++) html += '<td></td>';
html += '<td class="event-cell" colspan="'+days+'" style="background-color: '+task[3]+';"><span>'+task[4]+'% done</span>'+task[0]+'</td>';
if(daysAfter > 0) for(let j = 0; j < daysAfter; j++) html += '<td></td>';
html += '</tr>';
}
html += '</tbody></table>';
return html;
}
/**
* Calculate diff in days between two dates
* @param {date} the max date
* @param {date} the min date
* @returns {integer} num of days
*/
diffInDays(max, min){
var diffTime = Math.abs(max - min);
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}
}
Código CSS
/* Basic styles */
#gantt{
font-family: "Roboto";
}
#gantt table{
border-collapse: collapse;
border-spacing: 0px 20px;
}
table tr{
border-bottom: 5px solid white;
}
#gantt table tr th{
border: 1px solid white;
border-collapse: collapse;
padding: 9px;
font-size: 12px;
background-color: lightgray;
line-height: 35px;
}
#gantt table tr td{
padding: 5px;
line-height: 35px;
border-left: 1px dotted gray;
width: 250px;
}
#gantt table tr td:last-child{
border-right: 1px dotted gray;
}
#gantt table tr td.event-cell{
color: white;
font-size: 12px;
text-align: left;
padding-left: 10px;
border-radius: 26px;
border-left: none;
}
#gantt table tr td.event-cell:last-child{
border-right: none;
}
#gantt table tr td.event-cell span{
background-color: #f6a400;
padding: 5px 10px;
border-radius: 15px;
margin-right: 10px;
color: #685c43;
}