① 、Twproject Gantt甘特图介绍

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

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

jQuery 1

贰 、增加成效一:code自动层级编码,满意wbs编码需求

    工作分解结构 (WBS)
代码是体系的辨识你的分别显示结构中的每种职责的唯1个人置的字母数字代码。WBS
代码可用来报告日程和跟踪花费。在工程种类中,应用10分普遍,相关的编码还有OBS\RBS\PBS等等。

   在Microsoft Office
Project中的WBS代码有二种:大纲数字和自定义WBS代码。大纲数字是最简便的
WBS 编码类型。Microsoft Office Project
将自动计算每项职责大纲数字基础上的任务列表的纲领结构编号。例如,您的天职列表中的第3个义务的号码的
1。若是该职责具有多少个子职分,子职责是数码 1.① 、1.2 和
1.3。大纲数字只含有数字 (无号)
和不能够对其展开编辑。他们推行操作,可是,自动移动时更改职分向上或向下在职分列表中,当降级或升级职责。例如,尽管子职分当前有所的纲领数字为
3.5.4,并且移列表中的一行,大纲数字将自动更新为
3.5.3。假若下一场升级该相同的子职分,大纲数字将自动更新到 3.6。

   驾驭WBS编码的概念,扩张Twproject
Gantt的code编码,选用大纲数字。如下图:

jQuery 2

   
对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++;
            }
        }
    }
}

    本函数选择递归完毕:

jQuery 3

    调用步骤:

    定义甘特图: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页面。

三 、扩张作用二:让接纳的task出现在显示窗口

3.1 效果图

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

jQuery 4

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值,那是化解难点的首要。原甘特图如下:

jQuery 5

画布区域(莲灰部分)

jQuery 6

滚动区域(浅莲红部分)

    对应的dom层级结构如下:

jQuery 7

   
从Bar到体现区域,总共是4层嵌套。找到相应的bar,分析上层的节点间的借助关系,从以下陆个难题动手:

  • (1)怎样找到Bar?
  • (2)上层节点哪些起决定效用?
  • (3)画布区域与滚动区域的涉及怎么着?
  • (4)滚动区域的最大scrollLeft是有些?

标题一:怎样找到Bar?

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

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

难点二:上层节点哪些起到控制功用?

   
上层节点只有画布区域与滚动区域起到功效,bar在那多个区域的地方是什么的?通过分析dom结构,建立以下模型:

jQuery 8

模型示意图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是有个别

   
怎么着取得某一每二十13日,最大scollLeft。化解办法,通过chrome浏览器打开甘特图,将滚动区域的滑块拉到最左侧,在console窗口输入$(“div[class=’splitElement
splitBox2′]”).scrollLeft();可得到。如下图:

jQuery 9

3.4 数字分析分明依赖关系

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

jQuery 10

Excel分析图表1

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

var scrollScrollWidth = canvasWidth - scrollWidth + 17

    若是甘特图处于放到、裁减状态,是或不是创立呢?再一次测试结果如下:

jQuery 11

Excel分析图表2

   
无论甘特图怎么样缩放,公式照旧创建。这就找到了滚动窗口最大滑动区域scrollScrollWidth,bar的显示地点,对应的值就是scrollScrollWidth的一部分。把模型中的bar至于核心岗位,如下图:

jQuery 12

模型示意图2

    上海教室清晰的交付以下结论:left=centerLeft –
scrollWidth/2,总计滑块的职责,也等于找到left在滑块上的映射scrollLeft,结合scale周全,可总计出scrollLeft
= left * scale。

   
那样就兑现了原则性scrollLeft,真的是如此吧?经过测试,发现bar在滚动区域,并不在宗旨岗位。从分析方法来看,比较臃肿、复杂,要简化处理,如何是好吗?上面将再而三开始展览分销模型并优化。

3.5 模型深远剖析与优化

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

jQuery 13

模型示意图3

    遮挡区域上涨幅度maskWidth(maskWidth1+maskWidth2)=canvasWidth –
scrollWidth,与scrollScrollWidth相差17,也便是scrollScrollWidth≈maskWidth。而滚动条的留存,正是滑动遮挡区域,scrollLeft≈left,那样就非凡不难化了。考虑17呢?为啥是固定值?而不是变量值呢?

    为了弄懂那几个难题,我们接纳QQ截图滚动区域的垂直滚动条,如下图:

jQuery 14

   
揣摸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("-------------------------------------------------------");
    }
};

    运维后的效果图如下:

jQuery 15

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

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

相关文章

网站地图xml地图