Twproject Gantt开源甘特图功能扩展
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开源甘特图功能扩展的更多相关文章
- 【转载】 JQuery.Gantt(甘特图) 开发指南
转载来自: http://www.cnblogs.com/liusuqi/archive/2013/06/09/3129293.html JQuery.Gantt是一个开源的基于JQuery库的用于实 ...
- JQuery.Gantt(甘特图)开发
一.简介 JQuery.Gantt是一个开源的基于JQuery库的用于实现甘特图效果的可扩展功能的JS组件库. 二.前端页面 2.1 资源引用 首先需要将下载到的源码中的CSS.IMG.JS等资源放入 ...
- Twproject Gantt – 开源的 JavaScript 甘特图组件
Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees).内置编辑.缩放和 CSS 皮肤等功能.更重要的是,它是免费开源的. ...
- jquery 甘特图开发指南
JQuery.Gantt是一个开源的基于JQuery库的用于实现甘特图效果的可扩展功能的JS组件库. <link rel="stylesheet" href="cs ...
- 免费JS甘特图组件dhtmlxgantt
安装 参考:https://docs.dhtmlx.com/gantt/desktop__install_with_bower.html 可使用NuGet.Bower.npm包管理器安装(应用在asp ...
- 一款开源且功能强大的C#甘特图控件.NET Winforms Gantt Chart Control
甘特图在项目管理中非常重要,甘特图的思想比较简单,即以图示的方式通过活动列表和时间刻度形象地表示出任何特定项目的活动顺序与持续时间.它直观地表明任务计划在什么时候进行,及实际进展与计划要求的对比.管理 ...
- MVC使用Gantt Chart实现甘特图,管理事情进度
借助"甘特图",可以直观地了解任务.活动.工作的进度.dhtmlxGantt是一个开源的Javacirpt库,能帮助我们快速创建"甘特图",本篇体验在MVC中的 ...
- gantt甘特图可拖拽、编辑(vue、react都可用 highcharts)
前言 Excel功能强大,应用广泛.随着web应用的兴起和完善,用户的要求也越来越高.很多Excel的功能都搬到了sass里面.恨不得给他们做个Excel出来...程序员太难了... 去年我遇到了 ...
- 甘特图 (Gantt )的优缺点
时间管理 - 甘特图 (Gantt ) 优点:甘特图直观.简单.容易制作,便于理解,能很清晰地标识出直到每一项任务的起始与结束时间,一般适用比较简单的小型项目,可用于WBS的任何层次.进度控制.资源优 ...
随机推荐
- C# 注册 Windows 热键
闲扯: 前几日,一个朋友问我如何实现按 F1 键实现粘贴(Ctrl+V)功能,百度了一个方法,发给他,他看不懂(已经是 Boss 的曾经的码农),我就做了个Demo给他参考.今日得空,将 Demo 整 ...
- Java基础Map接口+Collections工具类
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- 多线程的通信和同步(Java并发编程的艺术--笔记)
1. 线程间的通信机制 线程之间通信机制有两种: 共享内存.消息传递. 2. Java并发 Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式执行,通信的过程对于程序员来说是完全透 ...
- iOS开发之Alamofire源码深度解析
今天博客中的Alamofire源码的版本是以现在最新的3.4版本为例.上篇博客系统的对NSURLSession相关的东西进行了详细的解析,详情请看<详解NSURLSession>,为了就是 ...
- 《JavaScript设计模式与开发实践》整理
最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...
- [原] KVM虚拟机网络闪断分析
背景 公司云平台的机器时常会发生网络闪断,通常在10s-100s之间. 异常情况 VM出现问题时,表现出来的情况是外部监控系统无法访问,猜测可能是由于系统假死,OVS链路问题等等.但是在出现网络问题的 ...
- spring applicationContext.xml和hibernate.cfg.xml设置
applicationContext.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans ...
- 用angular怎么缓存父页面数据
angular做单页面应用是一个比较好的框架,但是它有一定的入门难度,对于新手来说可能会碰到很多坑,也有许多难题,大部分仔细看文档,找社区是能解决的. 但有些问题也许资料比较少,最近遇到过一个要缓存父 ...
- BPM费控管理解决方案分享
一.方案概述费用是除经营成本外企业的最主要支出,费用管理是财务管理的核心之一,加强企业内控管理如:费用申请.费用报销.费用分摊.费用审批.费用控制和费用支付等,通过科学有效的管理方法规范企业费用管理, ...
- 查看mac中磁盘空间占用情况
今天发现磁盘空间不够了,首先要找到那些文件夹占用了磁盘空间. du命令很好使 du -c -d 1 -m | sort -n -c 显示当前文件夹总计占用空间 -d 1 层级为1,即只显示当前目录下一 ...