使用jQueryGantt实现进度甘特图

  由于项目需要,需要做一个进度甘特图。要求使用jQueryGantt来实现,在网上看了很多博客,终于找了几篇比较有用的。但是仅仅靠这几篇文章和一个demo无法满足项目的需求,所以研究了下jQueryGantt的源码,根据项目需求进行了一些改动。由于网上对于jQueryGantt的文章较少,很多都不完整,所以特此写下这篇文章进行记录,顺便分享有需要的人。

1.jQueryGantt下载

官方演示地址:http://taitems.github.io/jQuery.Gantt
我此次使用的是Github上一位网友发布的一个版本:https://github.com/ybx13579/jQuery.Gantt
这是他写的一份指南:https://blog.csdn.net/yangbingx/article/details/73470030
非常感谢,大家喜欢的记得给他一个star。

2.运行

这里的说明并不是很详细,具体参考test1文件夹中的index.html
将css,js,img放入工程项目中,并参考test1/index.html 中的引入。

注:如果需要甘特图中显示中文,则需要在js文件引用中加上charset特性并设置为GB2312,否则中文内容将显示为乱码。
<script src="js/jquery.fn.gantt.js" charset ="GB2312"></script>

之后在html页面上写一个div

   <style type="text/css">
        body {
            font-family: Helvetica, Arial, sans-serif;
            font-size: 13px;
            padding: 0 0 50px 0;
        }

        .contain {
            width: 800px;
            margin: 0 auto;
        }
    </style>


    <div class="gantt_ot" style="width:800px; margin:100px auto;">
        <div class="gantt"></div>
    </div>

复制相应的js方法

<script type="text/javascript">
    $(function () {
        var sourceData;
        $.ajax({
            url: "/test/getGanttData", //请求后台,并返回甘特图需要的json数据
            type: "post",
            dataType: "json",
            cache: false, //关闭AJAX缓存
            data: {"id": 1}, //传入的查询参数
            success: function (data) {

                //初始化gantt
                $(".gantt").gantt({
                    source: data,
                    navigate: 'scroll',//// 底部使用拖拽的刻度尺还是按钮:scroll和buttons
                    scale: "weeks",// 这里是设置默认比例。这里总共有四个参数:months  weeks days  hours.
                    maxScale: "months", // 这里是设置最大比例。这里总共有四个参数:months  weeks days  hours.
                    minScale: "days", // 这里是设置最小比例。这里总共有四个参数:months  weeks days  hours.
                    itemsPerPage: 20, //设置甘特图每页显示多少条
                    onItemClick: function (data) {//有数据范围内的点击事件
                        // alert("Item clicked - show some details");
                    },
                    onAddClick: function (dt, rowId) {//无数据范围内的点击事件
                        // alert("Empty space clicked - add an item!");
                    },
                    onRender: function () {//渲染事件
                        if (window.console && typeof console.log === "function") {
                            // console.log("chart rendered");
                        }
                    }
                });
            }
        });

        /*  //弹窗功能
          $(".gantt").popover({
              selector: ".bar",
              title: "I'm a popover",
              content: "And I'm the content of said popover.",
              trigger: "hover",
              placement: "auto right"
          });*/

        //prettyPrint();
    });


</script>

JQueryGantt需要的Json数据格式

[

                {
                    name: "task1",
                    desc: "",
                    values: [{
                        from: "/Date(1320192000000)/", //这里需要的时间为毫秒
            //。计算方式为时间变量减去时间初始值(1970-1-1)的差值换算为毫秒
                          to: "/Date(1320592000000)/",
                        label: "这是label",
                        customClass: "ganttRed" //这里是这条记录的在甘特图上的颜色
                    }]
                }, {
                    name: "task2",
                    desc: "这是描述",
                    values: [{
                        from: "/Date(1322611200000)/",
                        to: "/Date(1323302400000)/",
                        label: "",
                        customClass: "ganttGreen"
                    }]
                }]

如果你是使用的Java来编写的话,我这里提供一下后台处理json数据的思路。
首先,最外层的是一个List集合。然后里面的name,desc,values使用Map进行封装。而values里面又是一个集合,所以values整个呢诶容是一个List集合。而内部的from,to,label等参数又需要使用Map以[key,value]的形式保存。所以又要封装一个Map。

灵魂画手已上线
image.png

看了看自己画的图,还是贴代码吧。。。

//SpringMvc Framwork
@RequestMapping(value = "ganttData", method = RequestMethod.POST)
    @ResponseBody
    public String ganttData(String id) throws Exception {
          //查询出需要的多条进度数据
            List<Project> scheduleDataList = scheduleMgrService.selectScheduleDataListByPid(pt);
            //用于保存整个数据集
            List<Object> dataList = new ArrayList<>();
            //循环遍历,对数据进行重新封装
            for (ScheduleData data : scheduleDataList) {
               //用于存放 name,desc,value三个对象
                Map<String, Object> planItemMap = new HashMap<>();
                planItemMap.put("name", data.getSd_process_name() + "(计划)");
                planItemMap.put("desc", data.getSd_plan_remark());
                //用于存放value中的from,to,label,customClass
                Map<String, Object> valueMap = new HashMap<>();
                valueMap.put("from", "/Date(" + data.getSd_plan_start_date().getTime() + ")/");
                valueMap.put("to", "/Date(" + data.getSd_plan_end_date().getTime() + ")/");
                valueMap.put("label", "");
                valueMap.put("customClass", "ganttRed");
                //将封装的value的map封装到一个List集合中去
                List<Object> planValueList = new ArrayList<>();
                planValueList.add(valueMap);
                //将封装的value List集合添加到保存整个数据集的List里面去
                planItemMap.put("values", planValueList);
                dataList.add(planItemMap);
                }
          //将封装的数据集转换为Json数组
           JSONArray array = JSONArray.fromObject(dataList);
            //将Json数组转换为字符串并返回给前端
            return array.toString();
}
jQueryGantt.jpg

3.修改jQueryGantt的核心文件来满足项目的需求

问题:

下载的Demo中的jQueryGantt是一个宽度为800px的甘特图,但是项目中需要将甘特图横向铺满,所以必须将宽度设置为100%。但是jQueryGantt顶部的时间刻度是根据数据的时间长度生成的,在数据时间比较短并且在横向铺满屏幕的情况下就会出现时间刻度不全的情况。


image.png

当我只修改了div的宽度为自动或者100%的时候出现了上述情况。

    <div class="gantt_ot" style="width:auto; margin:100px auto;">
        <div class="gantt"></div>
    </div>

解决方法:

我不得不说,为了找到这个解决办法,我花了三个小时来阅读,调试,修改这个jquery.fn.gantt.js来解决这个问题。(可能是自己太菜了 2333333)。

(敲黑板) 重点来了~~
思路:空出来的地方用一年的刻度时间应该能填满,所以只要将jQueryGantt根据数据中的结束时间计算刻度尺长度的时间追加一年,就会多出一年的刻度时间出来。
打开jquery.fn.gantt.js
找到getMaxDate这个function
在所有的getFullYear()方法后面都追加一个 +1
maxDate.getFullYear()+1

贴出修改后的maxDate方法
// Return the maximum available date in data depending on the scale
//根据比例返回数据中的最大可用日期。
    getMaxDate: function (element) {
                var maxDate = null;
                $.each(element.data, function (i, entry) {
                    $.each(entry.values, function (i, date) {
                        maxDate = maxDate < tools.dateDeserialize(date.to) ? tools.dateDeserialize(date.to) : maxDate;
                    });
                });
                maxDate = maxDate || new Date();
                var bd;
                switch (settings.scale) {
                    case "hours":
                        maxDate.setHours(Math.ceil((maxDate.getHours()) / element.scaleStep) * element.scaleStep);
                        maxDate.setHours(maxDate.getHours() + element.scaleStep * 3);
                        break;
                    case "weeks":
                        // wtf is happening here?
                        bd = new Date(maxDate.getTime());
                        bd = new Date(bd.setDate(bd.getDate() + 3 * 7));
                        var md = Math.floor(bd.getDate() / 7) * 7;
                        maxDate = new Date(bd.getFullYear() + 1, bd.getMonth(), md === 0 ? 4 : md - 3);
                        break;
                    case "months":
                        bd = new Date(maxDate.getFullYear() + 1, maxDate.getMonth(), 1);
                        bd.setMonth(bd.getMonth() + 2);
                        maxDate = new Date(bd.getFullYear() + 1, bd.getMonth(), 1);
                        break;
                    case "days":
                    /* falls through */
                    default:
                        maxDate.setHours(0);
                        maxDate.setDate(maxDate.getDate() + 3);
                }
                return maxDate;
            },

这时你再刷新一下页面就会发现空白部分的网格和时间刻度被填上了。像这个样子


image.png

4.小优化

虽然最麻烦的问题得以解决。但是用户体验上还存在一些可以优化的地方,例如:月份为英文,星期为英文,底部的控件没有居中,这样用户感觉不太好。接下来我们逐一解决这些问题。

1.修改英文月份和周为中文。

打开jquery.fn.gantt.js
找到var settings这个变量的定义的地方,这里是jQueryGantt初始化参数的位置。

//Default settings 默认设置
var settings = {
            source: [],
            holidays: [],
            // 默认的页数
            itemsPerPage: 7,
            // localisation
            // dow: ["S", "M", "T", "W", "T", "F", "S"],
            //面板上的星期,只能为一个字,两个字会被挤出来
            dow: ["日", "一", "二", "三", "四", "五", "六"],
            //面板上的月份
            months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
          //甘特图在渲染的时候显示的提示文字
            waitText: "加载中,请稍候...",
            // 底部使用拖拽的刻度尺还是按钮:scroll和buttons
            navigate: "buttons",
            //网格加载完毕后是否自动滚动到今天,true为是 false为不需要
            scrollToToday: false,
            // cookie options
            useCookie: false,
            cookieKey: "jquery.fn.gantt",
            // scale parameters
            scale: "days",
            maxScale: "months",
            minScale: "hours",
            // callbacks
            onItemClick: function (data) {
                return;
            },
            onAddClick: function (dt, rowId) {
                return;
            },
            onRender: $.noop
        };
2.底部的控件居中

打开jQueryGantt的style.css

.gantt {
    width: 100%;
    margin: 0 auto; //清除掉上下间距
    border: 14px solid #ddd;
    position: relative;
    -webkit-border-radius: 6px;
   -moz-border-radius: 6px;
        border-radius: 6px;
  -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
        box-sizing: border-box;
}

//设置底部控件位置(前端技术有限,就这样简单的处理了一下)
.nav-slider {
    margin-left: 20%;
}
修改完后的效果图

到此为止,我的问题基本上都解决了~

参考文章:
https://blog.csdn.net/yangbingx/article/details/73470030
https://github.com/ybx13579/jQuery.Gantt
https://blog.csdn.net/weixin_41916005/article/details/80851748
https://blog.csdn.net/weixin_41916005/article/details/80851748
https://www.cnblogs.com/marksfly/p/4561165.html
https://blog.csdn.net/l3922768721/article/details/79933327
http://taitems.github.io/jQuery.Gantt/?yyue=a21bo.50862.201879
https://github.com/ybx13579/jQuery.Gantt

转载请注明出处及作者,谢谢。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,180评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,732评论 2 59
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,489评论 1 45
  • 年末的集市最热闹。 年就像一位已经定了婚期的待嫁闺女一样,需要置办嫁妆,从头换到脚,从里换到外,这买年货就像置办嫁...
    静笃流年阅读 426评论 10 7
  • 有一怜人兮,流落他乡 影只形单兮,满怀惆怅 涕泪纵横兮,情满陇上 问何所伤兮,唯念家乡 家之所在兮,遥指北方
    无谓的穿行者zr阅读 192评论 0 0