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. 试试SQLSERVER2014的内存优化表

    试试SQLSERVER2014的内存优化表 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技 ...

  2. Windows Server 2012 NIC Teaming介绍及注意事项

    Windows Server 2012 NIC Teaming介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Windows Ser ...

  3. ASP.NET是如何在IIS下工作的

    ASP.NET与IIS是紧密联系的,由于IIS6.0与IIS7.0的工作方式的不同,导致ASP.NET的工作原理也发生了相应的变化. IIS6(IIS7的经典模式)与IIS7的集成模式的不同 IIS6 ...

  4. ABP文档 - 嵌入的资源文件

    文档目录 本节内容: 简介 创建嵌入的文件 暴露嵌入的文件 使用嵌入的文件 简介 一个web应用里,客户端包含javascript,css,xml等文件,这此文件被添加到一个web项目后,发布成独立的 ...

  5. ExtJS 4.2 组件介绍

    目录 1. 介绍 1.1 说明 1.2 组件分类 1.3 组件名称 1.4 组件结构 2. 组件的创建方式 2.1 Ext.create()创建 2.2 xtype创建 1. 介绍 1.1 说明 Ex ...

  6. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  7. C++中的命名空间

    一,命名空间(namespace)的基本概念以及由来 1.什么是标识符: 在C++中,标识符可以是基本的变量,类,对象,结构体,函数,枚举,宏等. 2.什么是命名空间: 所谓的命名空间是指标识符的可见 ...

  8. DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)

    上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...

  9. git克隆项目到本地&&全局安装依赖项目&&安装依赖包&&启动服务

     一.安装本地开发环境 1.安装本项目 在需要保存到本地的项目的文件夹,进入到文件夹里点击右键,bash here,出现下图: 2.安装依赖项目  3.安装依赖包(进入到命令行) # 安装依赖包 $ ...

  10. MySQL 系列(四)主从复制、备份恢复方案生产环境实战

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...