Простая диаграмма Ганта на основе JS
Недавно мой коллега попросил небольшую просьбу и написал временную диаграмму Ганта, в основном для того, чтобы показать остановки автомобиля в разное время суток,
Давайте сначала посмотрим на эффект: спрос здесь с 5:00 утра до 5:00 утра.
Предварительная подготовка
На самом деле реализаций диаграмм Ганта в интернете много, но визуализировать их можно только до неба, а не до определенного момента времени, и описание в каждый конкретный период времени настроить нельзя, поэтому готов написать это сам. .
реализовать логику
Сначала мы можем смоделировать некоторые демонстрационные данные. Наиболее важные данные здесь - это каждый момент времени. Чтобы достичь вышеуказанного эффекта, нам нужно разделить каждый момент времени.
var demoData: [
{
carNum: '川A09384',
innerData: [
{
start: '2019/1/21 6:23',
end: '2019/1/21 7:45',
value: 'A站点',
bg: 'green'
},
{
start: '2019/1/21 12:23',
end: '2019/1/21 16:45',
value: 'B站点',
bg: 'yellow'
},
{
start: '2019/1/21 20:00',
end: '2019/1/21 23:25',
value: 'C站点',
bg: 'blue'
}
]
},
{ carNum: '川A04384',
innerData: [
{
start: '2019/1/21 5:23',
end: '2019/1/21 6:05',
value: 'A站点',
bg: 'blue'
},
{
start: '2019/1/21 10:23',
end: '2019/1/21 13:45',
value: 'B站点',
bg: 'green'
},
{
start: '2019/1/21 21:00',
end: '2019/1/22 3:35',
value: 'C站点',
bg: 'yellow'
},
]
}]
время первого создания
// 创建时间
createHours: function(){
var startHour = 5;
var endHour = 11;
var html = '';
for (let i = startHour; i< 24; i++) {
html += `<div>${i < 10 ? `0${i}` : i}:00</div>`
}
for (let i = 0; i< endHour; i++) {
html += `<div>${i < 10 ? `0${i}` : i}:00</div>`
}
document.getElementById('hour').innerHTML = html;
},
Нарисуйте диаграмму Ганта из данных
У нас будет 1H = 60px, таким образом зафиксируем ширину, то есть 1px = 1M;
Постройте первый временной период: начало: «2019/01/21 6:23», конец: «2019/1/21 7:45»;
var start = new Date('2019/1/21 6:23'),
end = new Date('2019/1/21 7:45'),
start_h = start.getHours(), // 开始时间
start_m = start.getMinutes(), // 开始分钟
end_h = end.getHours(), // 结束时间
end_m = end.getMinutes(), // 结束分钟
left_offset = 0;
_left_offset = 0;
width = '';
// 获取时间段甘特图的开始位置(我们从5点开始,所以-5);
left_offset = (start_h - 5) * 60 + start_m;
// 获取每一段甘特图的宽度,
// 先计算出结束时间的位置,然后在减去开始时间的左边距;
width = ((end_h - 5) * 60 + end_m) - left_offset;
// 使用现有的左边距减去前一个时间的左边距
_left_offset = left_offset - allLeft;
// 因为存在多个时间段,所以在绘制下一个时间断时,left_offset
// 使用allLeft存储上一个时间断距离左边的距离。
allLeft = left_offset + width;
// 将其添加到DOM中
html += `<span style="width:${width}px;margin-left:${_left_offset}px;">${innerData[i].value}</span>`;
- Сначала вам нужно найти начальную позицию начального времени в периоде времени,
- Рассчитайте ширину времени, следуя правилу 1px = 1M.
- При установке левого поля не забудьте вычесть левое поле (выделение) предыдущей диаграммы Ганта.
- После того, как линия не будет нарисована, сохраните ее левое поле для следующего периода времени.
О том, как считать по небу
Когда наш период времени принадлежит небу, как вычислить его начальную и конечную позиции, а также ширину? Вставьте код напрямую.
createData: function() {
var data = this.demoData;
var today = new Date().getDate(); // 今天的日期
for (let m = 0; m< data.length; m++) {
var innerData = data[m].innerData;
var html = '';
var allLeft = 0;
for (let i = 0; i< innerData.length; i++) {
var start = new Date(innerData[i].start),
end = new Date(innerData[i].end),
start_d = start.getDate(),
end_d = end.getDate(),
start_h = start.getHours(),
start_m = start.getMinutes(),
end_h = end.getHours(),
end_m = end.getMinutes(),
left_offset = 0;
_left_offset = 0;
width = '';
if (start_d === (today + 1)) {
left_offset = ((23 - 5) * 60) + ((start_h + 1) * 60) + start_m;
_left_offset = left_offset - allLeft;
width = (((23 + (end_h + 1)) - 5) * 60 + end_m) - left_offset;
} else if (end_d === (today + 1)) {
left_offset = ((start_h - 5) * 60) + start_m;
_left_offset = left_offset - allLeft;
width = (((24 + end_h) - 5) * 60 + end_m) - left_offset;
} else {
left_offset = (start_h - 5) * 60 + start_m;
_left_offset = left_offset - allLeft;
width = ((end_h - 5) * 60 + end_m) - left_offset;
}
allLeft = left_offset + width;
html += `<span style="width:${width}px;margin-left:${_left_offset}px;background:${innerData[i].bg}">${innerData[i].value}</span>`;
}
document.getElementById('container').innerHTML += `<div class="gantt-item" >${html}</div>`;
}
}
Это место не будет подробно объяснено. Если вам что-то непонятно, оставьте сообщение. Код очень лаконичен, в основном используется для реализации относительно простой диаграммы Ганта. Не нужно скачивать какие-либо плагины или что-то еще.
Разместите код здесь, все могут общаться друг с другом, возможно, у вас есть лучший способ его реализовать.
<html>
<head>
<title>测试demo</title>
<style type="text/css">
#container {
width: 100%;
overflow: scroll;
height: calc(100vh - 0px);
width: 1900px;
}
.carNum {
float:left;
width:100px;
text-align: center;
}
#hour {
width: 1800px;
overflow: scroll;
}
#hour div{
width: 60px;
float: left;
border-left: 1px solid #ddd;
background: #ccc;
text-align: center;
box-sizing: border-box;
}
.gantt-item {
width: 1800px;
}
.gantt-item:hover{
background:rgba(0,0,0,.1);
}
.gantt-item span {
height: 20px;;
display: inline-block;
margin: 5px 0px;
font-size: 12px;
text-align: center;
color:#fff;
background:green;
}
.nowTime {
border: 1px solid green;
display: inline-block;
height: 500px;
height: calc(100vh - 0px);
position: absolute;
top: 0px;
}
</style>
</head>
<body>
<div id="container">
<div class="carNum">
<div style="background:#ccc;">车牌号</div>
<div style="line-height:30px;">川A09384</div>
<div style="line-height:30px;">川A09384</div>
<div style="line-height:30px;">川A09384</div>
</div>
<div id="hour" style="float:righ">
</div>
</div>
</body>
<script type="text/javascript">
var gantt = {
demoData: [
{
innerData: [
{
start: '2019/1/21 6:23',
end: '2019/1/21 7:45',
value: 'A站点',
bg: 'green'
},
{
start: '2019/1/21 12:23',
end: '2019/1/21 16:45',
value: 'B站点',
bg: 'yellow'
},
{
start: '2019/1/21 20:00',
end: '2019/1/21 23:25',
value: 'C站点',
bg: 'blue'
}
]
},
{
innerData: [
{
start: '2019/1/21 5:23',
end: '2019/1/21 6:05',
value: 'A站点',
bg: 'blue'
},
{
start: '2019/1/21 10:23',
end: '2019/1/21 13:45',
value: 'B站点',
bg: 'green'
},
{
start: '2019/1/21 21:00',
end: '2019/1/22 3:35',
value: 'C站点',
bg: 'yellow'
},
]
},
{
innerData: [
{
start: '2019/1/21 8:23',
end: '2019/1/21 10:05',
value: 'A站点',
bg: 'blue'
},
{
start: '2019/1/21 13:23',
end: '2019/1/21 14:45',
value: 'B站点',
bg: 'green'
},
{
start: '2019/1/21 22:00',
end: '2019/1/22 3:35',
value: 'C站点',
bg: 'red'
},
{
start: '2019/1/22 4:00',
end: '2019/1/22 7:35',
value: 'D站点',
bg: 'green'
},
]
},
],
// 初始化
init: function() {
this.showNowTime();
this.createHours();
this.createData();
},
// 创建时间
createHours: function(){
var startHour = 5;
var endHour = 11;
var html = '';
for (let i = startHour; i< 24; i++) {
html += `<div>${i < 10 ? `0${i}` : i}:00</div>`
}
for (let i = 0; i< endHour; i++) {
html += `<div>${i < 10 ? `0${i}` : i}:00</div>`
}
document.getElementById('hour').innerHTML = html;
},
// 当前时间线
showNowTime: function() {
var date = new Date();
var h = date.getHours(),
m = date.getMinutes();
var offset = (h - 5) * 60 + m;
var html = `<div class="nowTime" style="margin-left:${offset}px"></div>`;
document.getElementById('container').innerHTML += `<div class="gantt-item">${html}</div>`;
},
createData: function() {
var data = this.demoData;
var today = new Date().getDate(); // 今天的日期
for (let m = 0; m< data.length; m++) {
var innerData = data[m].innerData;
var html = '';
var allLeft = 0;
for (let i = 0; i< innerData.length; i++) {
var start = new Date(innerData[i].start),
end = new Date(innerData[i].end),
start_d = start.getDate(),
end_d = end.getDate(),
start_h = start.getHours(),
start_m = start.getMinutes(),
end_h = end.getHours(),
end_m = end.getMinutes(),
left_offset = 0;
_left_offset = 0;
width = '';
if (start_d === (today + 1)) {
left_offset = ((23 - 5) * 60) + ((start_h + 1) * 60) + start_m;
_left_offset = left_offset - allLeft;
width = (((23 + (end_h + 1)) - 5) * 60 + end_m) - left_offset;
} else if (end_d === (today + 1)) {
left_offset = ((start_h - 5) * 60) + start_m;
_left_offset = left_offset - allLeft;
width = (((24 + end_h) - 5) * 60 + end_m) - left_offset;
} else {
left_offset = (start_h - 5) * 60 + start_m;
_left_offset = left_offset - allLeft;
width = ((end_h - 5) * 60 + end_m) - left_offset;
}
allLeft = left_offset + width;
html += `<span style="width:${width}px;margin-left:${_left_offset}px;">${innerData[i].value}</span>`;
}
document.getElementById('container').innerHTML += `<div class="gantt-item" >${html}</div>`;
}
}
}
gantt.init();
</script>
</html>