1、Twproject Gantt甘特图介绍

Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees)。内置编辑、缩放和 CSS 皮肤等功能。更重要的是,它是免费开源的。

官网地址是:https://gantt.twproject.com/ 源码可以从github下载:

2、扩展功能一:code自动层级编码,满足wbs编码要求

工作分解结构 (WBS) 代码是项目的识别您的分级显示结构中的每个任务的唯一位置的字母数字代码。WBS 代码可用于报告日程和跟踪成本。在工程系统中,应用非常广泛,相关的编码还有OBS\RBS\PBS等等。

在Microsoft Office Project中的WBS代码有两种:大纲数字和自定义WBS代码。大纲数字是最简单的 WBS 编码类型。Microsoft Office Project 将自动计算每项任务大纲数字基础上的任务列表的大纲结构编号。例如,您的任务列表中的第一个任务的编号的 1。如果该任务具有三个子任务,子任务是编号 1.1、1.2 和 1.3。大纲数字只包含数字 (无号) 和不能对其进行编辑。他们执行操作,但是,自动移动时更改任务向上或向下在任务列表中,当降级或升级任务。例如,如果子任务当前具有的大纲数字为 3.5.4,并且移列表中的一行,大纲数字将自动更新为 3.5.3。如果然后升级该相同的子任务,大纲数字将自动更新到 3.6。

理解WBS编码的概念,扩展Twproject Gantt的code编码,采用大纲数字。如下图:

对ganttMaster.js进行扩展,增加属性:isLevelCode(bool类型),是否自动对code进行编码。增加扩展方法levelCode:

GanttMaster.prototype.levelCode = function () {
if (this.tasks && this.tasks.length > 0) {
var curCodeExt = 1;
for (var i = 0; i < this.tasks.length; i++) {
var tsk = this.tasks[i];
if (tsk.level == 0) {
tsk.code = curCodeExt;
levelChildCode(tsk.getChildren(), tsk.code);
curCodeExt++;
}
}
} function levelChildCode(cTasks, prefix) {
if (cTasks && cTasks.length > 0) {
var curCodeExt = 1;
for (var i = 0; i < cTasks.length; i++) {
var tsk = cTasks[i];
tsk.code = prefix + "." + curCodeExt;
levelChildCode(tsk.getChildren(), tsk.code);
curCodeExt++;
}
}
}
}

本函数采用递归实现:

    调用步骤:

定义甘特图:var ge; //this is the hugly but very friendly global var for the gantt editor

加载甘特图模板: $("#ganttemplates").loadTemplates();

初始化甘特图:

          // here starts gantt initialization
ge = new GanttMaster();
//TODO:是否自动显示bar
ge.isBrowserTaskBar = true;
//TODO:设置code是否自动编码
ge.isLevelCode = true;
var workSpace = $("#workSpace");
workSpace.css({
width: $(window).width() - 20,
height: $(window).height() - 100
});
ge.init(workSpace)

加载数据并调用层级方法:

         function loadFromLocalStorage() {
var ret;
if (localStorage) {
if (localStorage.getObject("teamworkGantDemo")) {
ret = localStorage.getObject("teamworkGantDemo");
}
} else {
$("#taZone").show();
}
if (!ret || !ret.tasks || ret.tasks.length == 0) {
ret = JSON.parse($("#ta").val());
//actualiza data
var offset = new Date().getTime() - ret.tasks[0].start;
for (var i = 0; i < ret.tasks.length; i++)
ret.tasks[i].start = ret.tasks[i].start + offset;
//debugger;
}
ge.loadProject(ret);
ge.checkpoint(); //empty the undo stack
ge.levelCode();
}

可查看gantt213.html页面。

3、扩展功能二:让选择的task出现在显示窗口

3.1 效果图

选择task对应的gantt bar显示出来,且在滑动窗口居中显示,效果如下图:

3.2 ganttMaster修订

经过dom之间关系分析,找到其中的内在联系,主要增加如下方法:

GanttMaster.prototype.browserTaskBar = function (tsk) {
if (tsk && tsk instanceof Task) {
var id = tsk.id;
//找到taskBar
var taskBar = $("svg[taskid=\"" + id + "\"]");
var taskBarX = parseInt($(taskBar).attr("x"));
var taskBarWidth = parseInt($(taskBar).attr("width"));
//获取svg最外层画布canvas
var canvas = $(taskBar).parent().parent().parent();
var canvasWidth = $(canvas).width();
//获取滚动区域
var scroll = $(taskBar).parent().parent().parent().parent();
var scrollWidth = $(scroll).width();
var scrollScrollWidth = canvasWidth - scrollWidth + 17;
//获取水平滚动条要移动的位置
var centerLeft = (taskBarX + taskBarWidth / 2);
var scrollLeft = (centerLeft – scrollWidth/2) / canvasWidth * scrollScrollWidth;
console.log("-------------------------------------------------------");
console.log("canvas width:" + canvasWidth); //画布区域大小
console.log("scroll width:" + scrollWidth); //滚动区域大小
console.log("scroll scroll max width:" + scrollScrollWidth); //滚动区域最大滑动区域
console.log("scroll left position(old):" + $(scroll).scrollLeft()); //滚动区域滑块位置(旧)
$(scroll).scrollLeft(scrollLeft); //设置滑块位置
console.log("scroll left position(new):" + $(scroll).scrollLeft()); //滚动区域滑块位置(新)
console.log("-------------------------------------------------------");
}
};

方法讲解:根据taskid找到bar,获取对应的div层与滚动窗口,设置滚动窗口的scrollLeft。

注意:红色底纹17,是如何得到的呢?这个是滚动条宽度,3.4中有详细分析。

3.3 思路与模型

设置bar在滚动区域的中心位置,就是如何设置滚动区域的scrollLeft值,这是解决问题的关键。原甘特图如下:

画布区域(灰色部分)

滚动区域(灰色部分)

对应的dom层级结构如下:

从Bar到展示区域,总共是4层嵌套。找到对应的bar,分析上层的节点间的依赖关系,从以下4个问题入手:

    • (1)如何找到Bar?

    • (2)上层节点哪些起决定作用?
    • (3)画布区域与滚动区域的关系如何?
    • (4)滚动区域的最大scrollLeft是多少?

问题一:如何找到Bar?

Bar与任务项是联动的,两者是通过taskid进行关联的,比如找到taskid=-6的甘特图形:

        var id = -6;
//找到taskBar
var taskBar = $("svg[taskid=\"" + id + "\"]")

问题二:上层节点哪些起到决定作用?

上层节点只有画布区域与滚动区域起到作用,bar在这两个区域的位置是如何的?通过分析dom结构,建立以下模型:

模型示意图1

注意事项:(1)垂直滚动条暂不考虑。(2)task bar相对于画布区域的坐标x是不变的。

问题三:画布区域与滚动区域的关系如何?

从模型示意图来看,滚动区域必须而且正好可以查看画布区域,要保证这点,canvasWidth与scrollScrollWidth是一定的比例关系,则比例系数为scale=canvasWidth/scrollScrollWidth,表示滑动区域的比例,例如滑动区域向左滑动1,则画布区域则向右滑动scale。

(1)当出现滚动条时,canvasWidth>scrollScrollWidth>scrollWidth,而scale>1

(2)当滚动区域宽度增加时,scrollScrollWidth是在逐渐变小

(3)未出现滚动条时,scrollScrollWidth = 0

解惑,从模型来看,scrollWidth应该是大于scrollScrollWidth的吧?如何把比自己更大的画布区域包括进来,就是依靠滚动区域,这里可看作scrollScrollWidth是对scrollWidth的放大,其放到比例就是scale。

问题四:滚动区域最大scrollLeft是多少

如何获取某一时刻,最大scollLeft。解决办法,通过chrome浏览器打开甘特图,将滚动区域的滑块拉到最左边,在console窗口输入$("div[class='splitElement splitBox2']").scrollLeft();可得到。如下图:

3.4 数字分析确定依赖关系

根据chrome调试器,可获取canvasWidth、scrollWidth、scrollScrollWidth,甘特图原始状态下,使用两个浏览器记测试,数据记录如下:

Excel分析图表1

对canvasWidth-scrollWidth与scrollScrollWidth比较,绝对值都为17,得到结果为:

var scrollScrollWidth = canvasWidth - scrollWidth + 17

如果甘特图处于放到、缩小状态,是否成立呢?再次测试结果如下:

Excel分析图表2

无论甘特图如何缩放,公式依然成立。这就找到了滚动窗口最大滑动区域scrollScrollWidth,bar的显示位置,对应的值就是scrollScrollWidth的一部分。把模型中的bar至于中心位置,如下图:

模型示意图2

上图清晰的给出以下结论:left=centerLeft - scrollWidth/2,计算滑块的位置,也就是找到left在滑块上的映射scrollLeft,结合scale系数,可计算出scrollLeft = left * scale。

这样就实现了定位scrollLeft,真的是这样吗?经过测试,发现bar在滚动区域,并不在中心位置。从分析方法来看,比较臃肿、复杂,要简化处理,如何做呢?下面将继续进行分销模型并优化。

3.5 模型深入分析与优化

在模型分析中,没有对遮挡区域进行解析,分析图表如下:

模型示意图3

遮挡区域宽度maskWidth(maskWidth1+maskWidth2)=canvasWidth – scrollWidth,与scrollScrollWidth相差17,也就是scrollScrollWidth≈maskWidth。而滚动条的存在,正是滑动遮挡区域,scrollLeft≈left,这样就非常简单化了。考虑17呢?为什么是固定值?而不是变量值呢?

为了弄懂这个问题,我们使用QQ截图滚动区域的垂直滚动条,如下图:

推测17是垂直滚动条的宽度,对此可忽略不计,则scrollScrollWidth=maskWidth,可以看作scrollLeft=left=maskWidth1,实施也的确如此。

修订后的js代码如下(也包括获取svg相关属性的修订):

GanttMaster.prototype.browserTaskBar = function (tsk) {
if (tsk && tsk instanceof Task) {
var id = tsk.id;
//找到taskBar
var taskBar = $("svg[taskid=\"" + id + "\"]");
//var taskBarX = $(taskBar)[0].getBoundingClientRect().left;
var taskBarX = parseFloat($(taskBar)[0].getAttribute("x"));
var taskBarWidth = parseFloat($(taskBar)[0].getBoundingClientRect().width);
//获取svg最外层画布canvas
var canvas = $(taskBar).parent().parent().parent();
var canvasWidth = parseFloat($(canvas).width());
//获取滚动区域
var scroll = $(taskBar).parent().parent().parent().parent();
var scrollWidth = parseFloat($(scroll).width());
//获取水平滚动条要移动的位置
var centerLeft = (taskBarX + taskBarWidth / 2.0);
var scrollLeft = (centerLeft - scrollWidth / 2.0);
var oldScrollLeft = $(scroll).scrollLeft();
if (Math.abs(oldScrollLeft - scrollLeft) >= 1.0) {
$(scroll).scrollLeft(scrollLeft); //设置滑块位置
} else {
return;
}
console.log("-------------------------------------------------------");
console.log("task left:" + taskBarX);
console.log("task width:" + taskBarWidth);
console.log("canvas width:" + canvasWidth); //画布区域大小
console.log("scroll width:" + scrollWidth); //滚动区域大小
console.log("scroll left position(old):" + oldScrollLeft); //滚动区域滑块位置(旧)
console.log("scroll left position(new):" + scrollLeft); //滚动区域滑块位置(新)
console.log("-------------------------------------------------------");
}
};

运行后的效果图如下:

最终优化后的代码:http://files.cnblogs.com/files/zsy/gantt.rar

温馨提示,如对您有帮助,麻烦赞一下。~~~~~~~~~~

Twproject Gantt开源甘特图功能扩展的更多相关文章

  1. 【转载】 JQuery.Gantt(甘特图) 开发指南

    转载来自: http://www.cnblogs.com/liusuqi/archive/2013/06/09/3129293.html JQuery.Gantt是一个开源的基于JQuery库的用于实 ...

  2. JQuery.Gantt(甘特图)开发

    一.简介 JQuery.Gantt是一个开源的基于JQuery库的用于实现甘特图效果的可扩展功能的JS组件库. 二.前端页面 2.1 资源引用 首先需要将下载到的源码中的CSS.IMG.JS等资源放入 ...

  3. Twproject Gantt – 开源的 JavaScript 甘特图组件

    Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees).内置编辑.缩放和 CSS 皮肤等功能.更重要的是,它是免费开源的. ...

  4. jquery 甘特图开发指南

    JQuery.Gantt是一个开源的基于JQuery库的用于实现甘特图效果的可扩展功能的JS组件库. <link rel="stylesheet" href="cs ...

  5. 免费JS甘特图组件dhtmlxgantt

    安装 参考:https://docs.dhtmlx.com/gantt/desktop__install_with_bower.html 可使用NuGet.Bower.npm包管理器安装(应用在asp ...

  6. 一款开源且功能强大的C#甘特图控件.NET Winforms Gantt Chart Control

    甘特图在项目管理中非常重要,甘特图的思想比较简单,即以图示的方式通过活动列表和时间刻度形象地表示出任何特定项目的活动顺序与持续时间.它直观地表明任务计划在什么时候进行,及实际进展与计划要求的对比.管理 ...

  7. MVC使用Gantt Chart实现甘特图,管理事情进度

    借助"甘特图",可以直观地了解任务.活动.工作的进度.dhtmlxGantt是一个开源的Javacirpt库,能帮助我们快速创建"甘特图",本篇体验在MVC中的 ...

  8. gantt甘特图可拖拽、编辑(vue、react都可用 highcharts)

    前言   Excel功能强大,应用广泛.随着web应用的兴起和完善,用户的要求也越来越高.很多Excel的功能都搬到了sass里面.恨不得给他们做个Excel出来...程序员太难了... 去年我遇到了 ...

  9. 甘特图 (Gantt )的优缺点

    时间管理 - 甘特图 (Gantt ) 优点:甘特图直观.简单.容易制作,便于理解,能很清晰地标识出直到每一项任务的起始与结束时间,一般适用比较简单的小型项目,可用于WBS的任何层次.进度控制.资源优 ...

随机推荐

  1. Unity3d入门 - 关于unity工具的熟悉

    上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...

  2. hadoop 2.7.3本地环境运行官方wordcount-基于HDFS

    接上篇<hadoop 2.7.3本地环境运行官方wordcount>.继续在本地模式下测试,本次使用hdfs. 2 本地模式使用fs计数wodcount 上面是直接使用的是linux的文件 ...

  3. JavaScript Object对象

    目录 1. 介绍:阐述 Object 对象. 2. 构造函数:介绍 Object 对象的构造函数. 3. 实例属性:介绍 Object 对象的实例属性:prototype.constructor等等. ...

  4. Linux碎碎念

    在学习Linux过程中,有许多有用的小技巧.如果放在纸质的笔记本上,平时查阅会相当不方便.现在以一种“碎碎念”的方式,汇集整理在此,目前还不是很多,但随着学习.工作的深入,后续会陆陆续续添加更多的小技 ...

  5. js学习之类型识别

    用来判别类型的方法有好多,整理了一下4种方法,平时用的时候,在不同情景下,还是要结合着使用的. 方法一 typeof:可以识别标准类型,除了Null:不能识别具体的对象类型,除了Function &l ...

  6. 深入学习jQuery自定义插件

    原文地址:jQuery自定义插件学习 1.定义插件的方法 对象级别的插件扩展,即为jQuery类的实例增加方法, 调用:$(选择器).函数名(参数);      $(‘#id’).myPlugin(o ...

  7. C# 对象实例化 用json保存 泛型类 可以很方便的保存程序设置

    用于永久化对象,什么程序都行,依赖NewtonSoft.用于json序列化和反序列化. using Newtonsoft.Json; using System; using System.Collec ...

  8. 微软发布VSBT,无需安装Visual Studio即可实现项目编译

    安装了Visual Studio的那些使用微软平台的开发者通常能够非常容易地操作自己的项目:打开解决方案,修改内容,设置好所有必须的文件以及配置后编译项目.但是在构建服务器或者持续交付系统等没有安装V ...

  9. css3更改input单选和多选的样式

    在项目开发中我们经常会遇到需要更改input单选和多选样式的情况,今天就给大家介绍一种简单改变input单选和多选样式的办法. 在这之前先简单介绍一下:before伪类 :before 选择器向选定的 ...

  10. H5 canvas的 width、height 与style中宽高的区别

    Canvas 的width height属性 1.当使用width height属性时,显示正常不会被拉伸:如下 <canvas id="mycanvas" width=&q ...