基于JS实现简单甘特图

基于JS实现简单甘特图

最近同事求助到一个小小的需求,写一个时间甘特图,主要想表现一个车在一天的不同的时间点里,停靠的站点,

先来看一下效果吧,这里的需求是从早上的5点为开始时间,到第二天到凌晨5点
在这里插入图片描述

前期准备

其实网上有很多甘特图的实现方式,但是他们都只能具象到天,不能具体到某个时间点,而且每一个具体的时间段中的描述是不能自定义的,所以准备自己写一下了。

实现逻辑

我们可以先模拟一些demo数据,这里面最为主要的数据为每个时间点,我们要实现上面的效果,需要对每个时间点进行拆分。

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;

绘制第一个时间段 start:‘2019/1/21 6:23’; end: ‘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>`;
  1. 首先需要找到时间段中开始时间的开始位置,
  2. 计算出时间的width,遵循1px = 1M的规则。
  3. 在设置margin-left时,记得减去上一个时间段甘特图的margin-left(重点)。
  4. 没绘制一条后,存储其margin-left,方便下一个时间段使用。
关于跨天怎么计算

当我们的时间段是属于跨天的怎么计算他的开始和结束位置,以及他的宽度呢?直接贴代码了哈,

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>
  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 基于Vue的条形甘特图是通过使用Vue.js框架来实现的一种可视化工具,用于展示任务进度和时间表。在这种甘特图中,每个任务被表示为一条横向的条形,在整个工作流程中呈现顺序,代表任务的持续时间。 在Vue中,常用的条形甘特图插件有gantt-chart、VueGantt和vue2-gantt,它们通过简单的数据输入,即可自动生成甘特图。其中,gantt-chart可以在没有依赖关系的情况下直接使用,而VueGantt和vue2-gantt则提供了更多的数据和样式自定义选项。 条形甘特图可以用于跟踪项目计划的进度,管理资源和时间表,以及确定项目中存在的潜在问题。通过在Vue中使用条形甘特图,用户可以更轻松地处理大量数据,并在界面上动态地显示关键信息。 总之,基于Vue的条形甘特图是一种可视化工具,可帮助用户跟踪和管理项目任务进度和时间表,从而更好地规划和组织项目。在Vue中使用这种甘特图插件可以帮助用户更有效地处理数据和信息,并将其转化为具有意义的可视化展示。 ### 回答2: 基于Vue的条形甘特图是一个直观且动态的数据展示工具,使用Vue框架可以构建一个可复用的组件来实现该功能。 在这个组件中,首先需要定义一个数据格式,以便展示一个进度条,通常包含以下几个关键字段: - 名称:条形甘特图中每个任务或事件的名称; - 开始时间:任务或事件的开始时间; - 结束时间:任务或事件的结束时间; - 进度:当前任务或事件的完成进度。 在Vue组件中,可以使用v-for指令循环渲染所有的任务或事件,并根据数据中定义的时间段计算出每个任务或事件所在的位置和长度。同时,根据任务或事件的进度,可以添加不同颜色的进度条以表示当前任务或事件完成的程度。 除此之外,还可以根据需要添加更多的交互功能,例如:鼠标悬停时展示任务或事件的详细信息、点击某个任务或事件时跳转到相应的详情页等。 总之,基于Vue的条形甘特图是一个灵活、可定制且易于扩展的数据可视化工具,可以帮助用户有效展示项目进度和时间安排,提高工作效率和管理效果。 ### 回答3: 基于Vue的条形甘特图是一种新型的控件,它是Vue.js框架中的一种组件,可以快速、简便地构建出一个好看而且功能强大的甘特图甘特图可以有效地帮助我们管理项目进度和时间,更好地规划和安排工作计划和资源,提高工作效率。Vue的条形甘特图将这种特性和优势添加到了Web应用程序中。 这种甘特图通过多个条形来表示不同的任务或进程的时间量,这些条形放置在时间轴上,可以更好地展示出项目的进度和时间,用户可以通过甘特图更好地了解项目进展情况,了解各个任务的完成程度,更好地规划和安排工作。基于Vue的条形甘特图还支持显示进度百分比,时间刻度可以自定义,可以添加标签和标题等,非常方便和实用。 总之,基于Vue的条形甘特图是一种非常方便和实用的控件,可以帮助开发人员更好地管理和规划项目进度和时间,提高工作效率和项目成功率,非常值得尝试和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值