甘特图(Javascript实现)

简介

笔者在开发一个基于Web的应用程序提供对人物和项目事件的管理。项目需要一个甘特图 控件可视化表示任务列表,笔者尝试寻找自由可用的解决方案(因为不想增加开销)。笔者找到了一些例子,不过并不满意。于是,决定创建一个自己的甘特图控件。此次是笔者工作的最初成果。这个SIcon的最初版本只做了几个小时,所以仍会有些问题。尽管如此,笔者还是希望与各位分享,希望能帮助大家。

SICon现在支持FireFox浏览器!

背景

掌握和使用这个示例需要Jscript和 CSS知识。

使用代码

代码并不是很复杂,所以我在这里将展示全部:

脚本代码
  1.   1 /* --------- SICON GANTT CHART -----------------------------------------------------------
  2.   2  * AUTHOR        : Dathq - ICT Service Engineering Jsc, - [email]dathq@ise.com.vn[/email]
  3.   3  * LICENSE        : Free
  4.   4  * DESCRIPTION    : Create a new task item with these info
  5.   5  *        - from: start date (format: mm/dd/dddd)
  6.   6  *        - to: deadline of task (format: mm/dd/dddd)
  7.   7  *        - task: name of the task, what has to be solved (not includes ')
  8.   8  *        - resource: who have to solve this task (not includes ')
  9.   9  *        - progress: how is it going? (format: integer value from 0 to 100, not includes %)
  10. 10  *----------------------------------------------------------------------------------------*/
  11. 11 function Task(from, to, task, resource, progress)
  12. 12 {
  13. 13    var _from = new Date();   
  14. 14    var _to = new Date();
  15. 15    var _task = task;
  16. 16    var _resource = resource;                       
  17. 17    var _progress = progress;
  18. 18    var dvArr = from.split('/');
  19. 19    _from.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1, parseInt(dvArr[1], 10));
  20. 20    dvArr = to.split('/');
  21. 21    _to.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1, parseInt(dvArr[1], 10));       
  22. 22   
  23. 23    this.getFrom = function(){ return _from};
  24. 24    this.getTo = function(){ return _to};
  25. 25    this.getTask = function(){ return _task};
  26. 26    this.getResource = function(){ return _resource};
  27. 27    this.getProgress = function(){ return _progress};
  28. 28 }
  29. 29
  30. 30 function Gantt(gDiv)
  31. 31 {
  32. 32    var _GanttDiv = gDiv;
  33. 33    var _taskList = new Array();       
  34. 34    this.AddTaskDetail = function(value)
  35. 35    {
  36. 36        _taskList.push(value);
  37. 37       
  38. 38    }
  39. 39    this.Draw = function()
  40. 40    {
  41. 41        var _offSet = 0;
  42. 42        var _dateDiff = 0;
  43. 43        var _currentDate = new Date();
  44. 44        var _maxDate = new Date();
  45. 45        var _minDate = new Date();   
  46. 46        var _dTemp = new Date();
  47. 47        var _firstRowStr = "<table border=1 style='border-collapse:collapse'><tr><td rowspan='2' width='200px' style='width:200px;'><div class='GTaskTitle' style='width:200px;'>Task</div></td>";
  48. 48        var _thirdRow = "";
  49. 49        var _gStr = "";       
  50. 50        var _colSpan = 0;
  51. 51        var counter = 0;
  52. 52       
  53. 53        _currentDate.setFullYear(_currentDate.getFullYear(), _currentDate.getMonth(), _currentDate.getDate());
  54. 54        if(_taskList.length > 0)
  55. 55        {
  56. 56            _maxDate.setFullYear(_taskList[0].getTo().getFullYear(), _taskList[0].getTo().getMonth(), _taskList[0].getTo().getDate());
  57. 57            _minDate.setFullYear(_taskList[0].getFrom().getFullYear(), _taskList[0].getFrom().getMonth(), _taskList[0].getFrom().getDate());
  58. 58            for(i = 0; i < _taskList.length; i++)
  59. 59            {
  60. 60                if(Date.parse(_taskList.getFrom()) < Date.parse(_minDate))
  61. 61                    _minDate.setFullYear(_taskList.getFrom().getFullYear(), _taskList.getFrom().getMonth(), _taskList.getFrom().getDate());
  62. 62                if(Date.parse(_taskList.getTo()) > Date.parse(_maxDate))
  63. 63                    _maxDate.setFullYear(_taskList.getTo().getFullYear(), _taskList.getTo().getMonth(), _taskList.getTo().getDate());                       
  64. 64            }
  65. 65           
  66. 66            //---- Fix _maxDate value for better displaying-----
  67. 67            // Add at least 5 days
  68. 68           
  69. 69            if(_maxDate.getMonth() == 11) //December
  70. 70            {
  71. 71                if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1, _maxDate.getFullYear()))                   
  72. 72                    _maxDate.setFullYear(_maxDate.getFullYear() + 1, 1, 5); //The fifth day of next month will be used
  73. 73                else
  74. 74                    _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(), _maxDate.getDate() + 5); //The fifth day of next month will be used
  75. 75            }
  76. 76            else
  77. 77            {
  78. 78                if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1, _maxDate.getFullYear()))                   
  79. 79                    _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth() + 1, 5); //The fifth day of next month will be used
  80. 80                else
  81. 81                    _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(), _maxDate.getDate() + 5); //The fifth day of next month will be used
  82. 82            }
  83. 83           
  84. 84            //--------------------------------------------------
  85. 85           
  86. 86            _gStr = "";
  87. 87            _gStr += "</tr><tr>";
  88. 88            _thirdRow = "<tr><td> </td>";
  89. 89            _dTemp.setFullYear(_minDate.getFullYear(), _minDate.getMonth(), _minDate.getDate());
  90. 90            while(Date.parse(_dTemp) <= Date.parse(_maxDate))
  91. 91            {   
  92. 92                if(_dTemp.getDay() % 6 == 0) //Weekend
  93. 93                {
  94. 94                    _gStr += "<td class='GWeekend'><div style='width:24px;'>" + _dTemp.getDate() + "</div></td>";
  95. 95                    if(Date.parse(_dTemp) == Date.parse(_currentDate))                       
  96. 96                        _thirdRow += "<td id='GC_" + (counter++) + "' class='GToDay' style='height:" + (_taskList.length * 21) + "'> </td>";
  97. 97                    else
  98. 98                        _thirdRow += "<td id='GC_" + (counter++) + "' class='GWeekend' style='height:" + (_taskList.length * 21) + "'> </td>";
  99. 99                }
  100. 100                else
  101. 101                {
  102. 102                    _gStr += "<td class='GDay'><div style='width:24px;'>" + _dTemp.getDate() + "</div></td>";
  103. 103                    if(Date.parse(_dTemp) == Date.parse(_currentDate))                       
  104. 104                        _thirdRow += "<td id='GC_" + (counter++) + "' class='GToDay' style='height:" + (_taskList.length * 21) + "'> </td>";
  105. 105                    else
  106. 106                        _thirdRow += "<td id='GC_" + (counter++) + "' class='GDay'> </td>";
  107. 107                }
  108. 108                if(_dTemp.getDate() < getDaysInMonth(_dTemp.getMonth() + 1, _dTemp.getFullYear()))
  109. 109                {
  110. 110                    if(Date.parse(_dTemp) == Date.parse(_maxDate))
  111. 111                    {                           
  112. 112                        _firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>T" + (_dTemp.getMonth() + 1) + "/" + _dTemp.getFullYear() + "</td>";                           
  113. 113                    }
  114. 114                    _dTemp.setDate(_dTemp.getDate() + 1);
  115. 115                    _colSpan++;
  116. 116                }                   
  117. 117                else
  118. 118                {
  119. 119                    _firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>T" + (_dTemp.getMonth() + 1) + "/" + _dTemp.getFullYear() + "</td>";
  120. 120                    _colSpan = 0;
  121. 121                    if(_dTemp.getMonth() == 11) //December
  122. 122                    {
  123. 123                        _dTemp.setFullYear(_dTemp.getFullYear() + 1, 0, 1);
  124. 124                    }
  125. 125                    else
  126. 126                    {
  127. 127                        _dTemp.setFullYear(_dTemp.getFullYear(), _dTemp.getMonth() + 1, 1);
  128. 128                    }
  129. 129                }                   
  130. 130            }
  131. 131            _thirdRow += "</tr>";               
  132. 132            _gStr += "</tr>" + _thirdRow;               
  133. 133            _gStr += "</table>";
  134. 134            _gStr = _firstRowStr + _gStr;               
  135. 135            for(i = 0; i < _taskList.length; i++)
  136. 136            {
  137. 137                _offSet = (Date.parse(_taskList.getFrom()) - Date.parse(_minDate)) / (24 * 60 * 60 * 1000);
  138. 138                _dateDiff = (Date.parse(_taskList.getTo()) - Date.parse(_taskList.getFrom())) / (24 * 60 * 60 * 1000) + 1;
  139. 139                _gStr += "<div style='position:absolute; top:" + (20 * (i + 2)) + "; left:" + (_offSet * 27 + 204) + "; width:" + (27 * _dateDiff - 1 + 100) + "'><div title='" + _taskList.getTask() + "' class='GTask' style='float:left; width:" + (27 * _dateDiff - 1) + "px;'>" + getProgressDiv(_taskList.getProgress()) + "</div><div style='float:left; padding-left:3'>" + _taskList.getResource() + "</div></div>";
  140. 140                _gStr += "<div style='position:absolute; top:" + (20 * (i + 2) + 1) + "; left:5px'>" + _taskList.getTask() + "</div>";
  141. 141            }
  142. 142            _GanttDiv.innerHTML = _gStr;
  143. 143        }
  144. 144    }
  145. 145 }       
  146. 146
  147. 147 function getProgressDiv(progress)
  148. 148 {
  149. 149    return "<div class='GProgress' style='width:" + progress + "%; overflow:hidden'></div>"
  150. 150 }
  151. 151 // GET NUMBER OF DAYS IN MONTH
  152. 152 function getDaysInMonth(month, year) 
  153. 153 {
  154. 154   
  155. 155    var days;       
  156. 156    switch(month)
  157. 157    {
  158. 158        case 1:
  159. 159        case 3:
  160. 160        case 5:
  161. 161        case 7:
  162. 162        case 8:
  163. 163        case 10:
  164. 164        case 12:
  165. 165            days = 31;
  166. 166            break;
  167. 167        case 4:
  168. 168        case 6:
  169. 169        case 9:
  170. 170        case 11:
  171. 171            days = 30;
  172. 172            break;
  173. 173        case 2:
  174. 174            if (((year% 4)==0) && ((year% 100)!=0) || ((year% 400)==0))               
  175. 175                days = 29;               
  176. 176            else                               
  177. 177                days = 28;               
  178. 178            break;
  179. 179    }
  180. 180    return (days);
  181. 181 }               
  182. 182 /*----- END OF MY CODE FOR Gantt CHART GENERATOR -----*/
复制代码
如何使用这段脚本

在你的HTML, ASCX, ASPX或PHP文档的Body部分,把下面几行代码拷贝到你想表示甘特图的地方。
  1. 1 <body>   
  2. 2    <h3>Diagram</h3>   
  3. 3    <div style="position:relative" class="Gantt" id="GanttChart"></div>
  4. 4 </body>
  5. 5 <script>
  6. 6    var g = new Gantt(document.all.GanttChart);
  7. 7    g.AddTaskDetail(new Task('2/11/2008', '2/12/2008',
  8. 8                    '<b>Sample task 1 1</b>', 'Dathq', 50));
  9. 9    g.AddTaskDetail(new Task('2/16/2008', '2/19/2008',
  10. 10                    ' Sample task 1.1', 'Dathq, Thanhdd', 30));
  11. 11    g.AddTaskDetail(new Task('2/12/2008', '3/4/2008', 'Sample task 2', 'Hanhnd', 60));
  12. 12    g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', 'Sample task 3', 'Dathq', 50));
  13. 13   
  14. 14    g.Draw();   
  15. 15 </script>
复制代码
使用var g = new Gantt(document.all.GanttChart);语句指定你要显示的甘特图到命名为"GanttChart"的DIV元素(你可以在body中看到它)。

g.AddTaskDetail()方法添加任务到任务列表。你可以使用AJAX或任何你喜欢的方式来生成这些命令以添加任务的集合。

使用g.Draw()来渲染基于追加到甘特图对象的任务列表的甘特图。

如何改变组件外观

这里笔者定义了一些类用来自定义甘特图的样式,为此提供了全部代码。你可以定义更多的类并且更轻易地改变甘特图控件的外观。

通过改变样式表,并且在代码中添加属性到任务对象,你可以为你自己创建更加智能的甘特图。例如:为任务条设置不同的颜色,漂亮的背景图片,更好的图标提示等等。

样式表
  1. 1    /*----- SICON GANTT CHART STYLE CLASSES --------------------------
  2. 2      * DESCRIPTION    : Theses class is required for SIcon Gantt Chart
  3. 3      * NOTE            : Should change the color, the text style only
  4. 4      *----------------------------------------------------------------*/
  5. 5    .Gantt
  6. 6    {
  7. 7        font-family:tahoma, arial, verdana;
  8. 8        font-size:11px;
  9. 9    }
  10. 10   
  11. 11    .GTaskTitle
  12. 12    {
  13. 13        font-family:tahoma, arial, verdana;
  14. 14        font-size:11px;
  15. 15        font-weight:bold;
  16. 16    }
  17. 17   
  18. 18    .GMonth
  19. 19    {
  20. 20        padding-left:5px;
  21. 21        font-family:tahoma, arial, verdana;
  22. 22        font-size:11px;
  23. 23        font-weight:bold;   
  24. 24    }
  25. 25   
  26. 26    .GToday
  27. 27    {
  28. 28        background-color: #FDFDE0;   
  29. 29    }
  30. 30   
  31. 31    .GWeekend
  32. 32    {
  33. 33        font-family:tahoma, arial, verdana;
  34. 34        font-size:11px;
  35. 35        background-color:#F5F5F5;
  36. 36        text-align:center;
  37. 37    }
  38. 38   
  39. 39    .GDay
  40. 40    {
  41. 41        font-family:tahoma, arial, verdana;
  42. 42        font-size:11px;
  43. 43        text-align:center;
  44. 44    }
  45. 45   
  46. 46    .GTask
  47. 47    {
  48. 48        border-top:1px solid #CACACA;
  49. 49        border-bottom:1px solid #CACACA;
  50. 50        height:14px;
  51. 51        background-color:yellow;
  52. 52    }
  53. 53   
  54. 54    .GProgress
  55. 55    {
  56. 56        background-color:black;
  57. 57        height:2px;
  58. 58        overflow: hidden;
  59. 59        margin-top:5px;
  60. 60    }
复制代码
图表

Code
  1. 1    var g = new Gantt(document.all.GanttChart);
  2. 2    g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', '<b>Sample task 1 1</b>', 'Dathq', 50));
  3. 3    g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', ' Sample task 1.1', 'Dathq, Thanhdo', 30));
  4. 4    g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
  5. 5    g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', '<i>Sample task 3<i>', 'Dathq', 50));
  6. 6    g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', '<b>Sample task 1 1</b>', 'Dathq', 50));
  7. 7    g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', ' Sample task 1.1', 'Dathq, Thanhdo', 30));
  8. 8    g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
  9. 9    g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', '<i>Sample task 3<i>', 'Dathq', 50));
  10. 10    g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', '<b>Sample task 1 1</b>', 'Dathq', 50));
  11. 11    g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', ' Sample task 1.1', 'Dathq, Thanhdo', 30));
  12. 12    g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
  13. 13    g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', '<i>Sample task 3<i>', 'Dathq', 50));
  14. 14
  15. 15    g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', '<b>Sample task 1 1</b>', 'Dathq', 50));
  16. 16    g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', ' Sample task 1.1', 'Dathq, Thanhdo', 30));
  17. 17    g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
  18. 18    g.AddTaskDetail(new Task('5/11/2008', '5/16/2008', '<i>Sample task 3<i>', 'Dathq', 50));
  19. 19
  20. 20    g.Draw();
复制代码

兴趣点

你会先注意到图标运行起来速度很快。

SIcon甘特图是通过Javascript创建的,这意味着你可以在众多的Web开发环境中使用它。我比较喜欢ASP.NET,所以我会把此控件和ASP.NET一起使用。另外,你可以使用AJAX创建更酷的应用。你可以自定义CSS类得到更好看的甘特图。我将试图添加链接到任务用来描述他们的关系,并将显示一个父任务,就像我们在MS Project中看到的一样。

甘特图通过HTML显示,因为它使用的是轻量级结构,所以你可以添加更多的功能到图表。例如,提示、链接、图片等,在JScript中使用一些基本的变化就可以获得。

最后,它是全免费的,编码愉快!

原文地址: http://www.codeproject.com/KB/scripting/SIcon_Gantt_Chart.aspx     http://www.pin5i.com/showtopic-20094.html

 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值