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的任何层次.进度控制.资源优 ...
随机推荐
-
关于Java中的基本数据类型转换
Java中的基本类型有四种,其中整型分为byte.short.int.long,浮点型分为float.double,字符型char,布尔型boolean.8种类型的级别由低到高byte->sho ...
-
Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
我们到底能走多远系列(33) 扯淡: 各位: 命运就算颠沛流离 命运就算曲折离奇 命运就算恐吓着你做人没趣味 别流泪 心酸 更不应舍弃 ... 主题: Spring源码阅读还在继 ...
-
HTTP 500 - 内部服务器错误
问题1 问:当调试程序出错的时候,为什么有的机器总是出现“HTTP 错误 500.100 - 内部服务器错误 - ASP 错误”,而不能显示具体的出错信息? 原因: IE浏览器设置中屏蔽掉了出错的具体 ...
-
sqlite 获取数据库中的所有表
SELECT name from sqlite_master where type='table'
-
想询问一个职业规划的问题,前端开发 or nodejs?
先说说个人情况,目前个人定位于初中级前端吧,工作近两年,目前前端开发和nodejs都有一定的了解,水平感觉可以搭一些小型的网站.作为前端开发,目前掌握的技术是javascript,平时更多的是用jqu ...
-
day_7数据类型的相互转换,与字符编码
首先复一下昨天的内容 1:深浅拷贝 1:值拷贝 直接赋值 列表1=列表2 列表1中的任何值发生改变,列表2中的值都会随之改变 2:浅拷贝,列表2=列表1 列表1中存放的值的地址没有改变, ...
-
DButils实现数据库表下划线转bean中驼峰格式
准备: QueryRunner queryRunner = new QueryRunner();//开启下划线->驼峰转换所用BeanProcessor bean = new GenerousB ...
-
redis内部数据结构深入浅出
最大感受,无论从设计还是源码,Redis都尽量做到简单,其中运用到的原理也通俗易懂.特别是源码,简洁易读,真正做到clean and clear, 这篇文章以unstable分支的源码为基准,先从大体 ...
-
samba安装
第一步下载: wget https://download.samba.org/pub/samba/stable/samba-4.6.7.tar.gz 看了下没看到啥有用的直接安装: ./configu ...
-
stm32初做项目心得
在导师的带领下,基本了解了嵌入式的开发的基本流程: 1.首先从厂家拿到样板之后,首先进行检测,检测什么呢,先检测电源系统,看你的电源系统是否能够正常工作,就是各个管脚是否短路,断路. 2.检测完之后, ...