前些天一直在弄web甘特圖,發現網上很多web甘特圖框架,但大部分是收費的。偶爾發現了向日葵甘特圖 感覺不錯,特此寫下來一方面當做記錄,另一方面也為尋找web甘特圖的同學們少走一些彎路,雙贏嘛~
View Code
向日葵甘特圖是純js編寫,相比於其他龐大的甘特圖應用,好處不用多說:輕便易於和網頁應用嵌套(其他的同學們可以自己體會)。 網上提供了一個遠程js庫和相應API,我們可以方便的進行二次開發。同學們網上一搜即可找到。
本甘特圖以XML作為數據傳輸格式,基本格式如下:
<
Tasks
>
<
Task
>
<
UID
>
0
</
UID
> //唯一任務編號
<
ID
>
0
</
ID
>
<
Name
>
住宅建設
</
Name
> //任務名稱
<
OutlineNumber
>
0
</
OutlineNumber
> //大綱號碼
<
Start
>
2004-01-01T08:00:00
</
Start
> //開始時間
<
Finish
>
2004-07-30T17:00:00
</
Finish
> //結束時間
<
Summary
>
1
</
Summary
> //是否摘要
<PredecessorLink>
<PredecessorUID>3</PredecessorUID>
//前置任務uid
<Type>1</Type> //前置任務關系1:完成-完成2:完成-開始3:開始-完成4:開始-開始
</PredecessorLink>
</
Task
>
</Tasks>
每個task代表一個任務,前台甘特圖頁面數據就是xml格式傳遞的。
下面介紹甘特圖中幾個重要的對象。
- 一。SFData:此對象為甘特數據核心對象,負責創建任務數據、資源數據、鏈接數據、資源分配數據等。xml數據讀取存儲到此對象中,然后以sfdata為數據中心。
- 二。數據適配器:主要包括SFDataProject和SFDataXml兩個對象,用於將xml數據導入到SFData中,下面分別介紹。
- SFDataProject:支持直接將微軟project的xml格式數據作為數據源導入到SFData.
- SFDataXml:采用向日葵甘特圖指定的XML格式作為數據源的數據適配器對象,這種xml格式是在ms project的xml格式的基礎上,進行一些節點的調整以提升Web性能,支持延時加載,並支持按需下載技術;
三。sfdatatask sfdatalink sfdataresource sfdataAssignment等對象,分別對應
任務數據、
鏈接數據、
資源數據、
資源分配數據,這些對象主要對具體的任務、鏈接、資源、資源分配等進行相關操作。
三者具體關系見下圖:
四。SFConfig對象:
甘特圖(SFGantt JavaScript API)之中用來對甘特圖進行配置的類,配置的方式可以使用Json,也可以通過類的方法進行配置。如下格式:
gtConfig.setConfig(
"SFGantt/taskIdFieldNames"
,
"ID"
); 可設置第一列值為ID號,具體用法參見API
五。SFGantt對象:甘特圖對象,本對象是甘特圖的主體對象,代表頁面上的甘特圖實例,你也可以在頁面上運行多個甘特圖實例 可以完成添加功能控件、設置升/降級、設置頁面顯示等功能。
下面用兩個示例分別演示具體用法:
實例一: xml格式操作甘特圖(無數據庫交互)
此甘特圖采用ajax獲取數據:
SFAjax.loadXml(
"test.xml"
,onGanttLoaded);
//通過Ajax模式下載對應的XML文件,並在下載完成之后執行onDataLoaded函數
function
onGanttLoaded(doc)
//doc參數是一個XML文件DOM對象
{
var
gtConfig=
new
SFConfig();
//初始化一個頁面上的配置對象
gtConfig.setConfig(
"SFGantt/container"
,
"Div_Gantt"
);
//設置用來顯示甘特圖的層的ID
gtConfig.setConfig(
"SFGantt/taskIdFieldNames"
,
"ID"
);
//設置甘特圖編號列顯示的字段,缺省為空,這里將其設置為ID
gtData=
new
SFData(
new
SFDataProject(doc));
//將doc對象初始化為一個甘特數據對象
gtData.addComponent(
new
SFDataIDComponent());
//使用向日葵甘特SFDataIDComponent數據插件
gtMap =
new
SFGantt(gtConfig,gtData);
//用相應的數據對象和配置對象創建甘特對象
SFEvent.addListener(gtMap,
"linkclick"
,onLinkdblClick);
//任務雙擊事件
SFGanttField.getTaskField(
"Start"
).setInputHandle(InputHandle_DateTime);
//設置開始日期輸入方式
SFGanttField.getTaskField(
"Finish"
).setInputHandle(InputHandle_DateTime);
//設置結束日期輸入方式
gtMap.showMap(
null
,5);
//顯示甘特圖
}
具體類用法讀者們可查閱提供的API文檔
實例二:與數據庫交互的。
代碼如下:

1 function onLoad()
//
在頁面初始化的時候執行本函數
2 {
3 // 通過servlet獲取甘特圖所需要的xml數據
4 SFAjax.loadXml("servlet/dataProvider?uid=" +projectUid+"&action=getRootTask&t="+ new Date().valueOf(),onGanttLoaded);
5 }
6 function onGanttLoaded(doc) // doc參數是一個XML文件DOM對象
7 {
8 var gtConfig= new SFConfig(); // 初始化一個頁面上的配置對象
9 gtConfig.setConfig( "SFGantt/container","Div_Gantt" ); // 設置用來顯示甘特圖的層的ID
10
11 var adapter= new SFDataXml(doc);
12
13 // 自定擴展一個責任人域,設置一個負責人維護域 Dutier
14 // 設置責任人字段,通知適配器adapter從 xml中讀取這個屬性,這樣Task對象會擴展出 Dutier屬性,
15 // 注意第二個參數的大小寫與 xml標簽相同
16 adapter.addTaskProperty( "Dutier","DUTIER" ,SFDataRender.types.String);
17 // 第二步:用setTaskField函數來設置責任人甘特屬性域,域顯示方式 headstyle,bodystyle ,inputstyle可使用樣式表,支持更靈活的顯示方式
18 var field1= new SFGanttField({width:100,bodyData:'Dutier' ,inputData:'Dutier',headText: '負責人',headStyle:{textAlign:'left' },bodyStyle: {textAlign:'right'}})
19 SFGanttField.setTaskField( "Dutier",field1);
20
21 // 修改已有甘特域的顯示屬性和輸入屬性
22 SFGanttField.getTaskField( "OutlineNumber").setHeadText("WBS" ); // 設置顯示方式
23 SFGanttField.getTaskField( "Start").setInputHandle(InputHandle_DateTime); // 設置開始日期輸入方式
24 SFGanttField.getTaskField( "Finish").setInputHandle(InputHandle_DateTime); // 設置結束日期輸入方式
25 // 設置甘特圖顯示字段屬性
26 gtConfig.setConfig( "SFGantt/taskFieldNames","StatusIcon,Name,Start,Finish,Duration,Dutier,OutlineNumber" ); // 設置甘特圖顯示的字段列表
27
28 // 初始化甘特圖數據對象
29 gtData= new SFData(adapter);
30 // 初始化甘特圖日志對象,初始化日志對象后,系統才會記錄修改日志,用於向后台發送修改內容。設置記錄日志內容
31 gtLog= new SFDataLogging(gtData);
32 gtLog.setTaskFields( "Name,Start,Finish,Summary,PercentComplete,Dutier,Notes" )
33
34
35 // 添加插件
36 // 添加大綱級別插件
37 gtData.addComponent( new SFDataOutlineComponent()); // 使用向日葵甘特SFDataOutlineComponent數據插件
38
39 // 根據配置和數據產生甘特數據
40 gtMap= new SFGantt(gtConfig,gtData);
41
42 // 設置甘特圖的事件
43 // 增加甘特圖事件SFEvent.addListener
44 // 第一個參數為 gantt數據 gtData
45 // 第二個參數為事件名稱
46 // 第三個參數為事件激發時的調用函數
47 SFEvent.addListener(gtData, "aftertaskadd",onAfterTaskAdd); // 添加任務之后調用事件產生唯一順序號 guid
48 SFEvent.addListener(gtData, "afterlinkadd",onAfterLinkAdd); // 添加鏈接之后調用事件產生唯一順序號 guid
49 SFEvent.addListener(gtData, "aftertaskchange",onAfterTaskChange); // 任務屬性賦值事件
50 SFEvent.addListener(gtMap, "linkclick",onLinkdblClick); // 鏈接線點擊事件任務屬性賦值事件
51 // 計算所有任務的工期,任務都按照固定工期進行運算。
52 initDuration();
53 /* gtMap.addControl(aaa=new SFGanttProgressLine("2009-12-02 18:00:00",{
54 vertexImg:' http://www.51diaodu.cn/sfgantt/img/task_head_20.gif ',
55 vertexSize:[10,10],
56 vertexStyle:{border:'solid 1px green'},
57 lineColor:'black',
58 lineWeight:1
59 })); */
60
61 // 增加項目進度線
62 pgl= new SFGanttProgressLine("2004-12-02 18:00:00" );
63 gtMap.addControl(pgl);
64
65 // 甘特圖顯示,第一個參數用於甘特圖初始化顯示時的 左邊界,第二個參數用於顯示比例
66 gtMap.showMap(SFGlobal.getDate( "2009-11-18 00:00:00"),4);
67
68
69 }
70
71
72 function save()
73 {
74
75 var xmlDom=gtLog.getXml(); // 獲得更新記錄的XML文件
76 var strLog=SFAjax.getXmlString(xmlDom);
77 alert( "發送到后台的更改記錄為:\n" +strLog);
78 var params=[];
79 // 在這里計算出此任務的順序
80 params.push( "action=save");
81 params.push( "t="+ new Date().valueOf());
82 params.push( "uid="+projectUid);
83
84 SFAjax.loadXml("servlet/dataResolver?" +params.join("&"), function(doc)
85 {
86 if(doc.documentElement.getAttribute("errorCode" )=="0")
87 {
88 gtLog.clear(); // 如果存盤成功,就重置所有變更信息
89 alert( "數據保存成功!" );
90 }
91 else
92 {
93 alert( "?"+params.join("&" ));
94 alert(doc.documentElement.firstChild?doc.documentElement.firstChild.nodeValue:"未知錯誤");
95 }
96
97
98 }, false,strLog);
99
100 }
2 {
3 // 通過servlet獲取甘特圖所需要的xml數據
4 SFAjax.loadXml("servlet/dataProvider?uid=" +projectUid+"&action=getRootTask&t="+ new Date().valueOf(),onGanttLoaded);
5 }
6 function onGanttLoaded(doc) // doc參數是一個XML文件DOM對象
7 {
8 var gtConfig= new SFConfig(); // 初始化一個頁面上的配置對象
9 gtConfig.setConfig( "SFGantt/container","Div_Gantt" ); // 設置用來顯示甘特圖的層的ID
10
11 var adapter= new SFDataXml(doc);
12
13 // 自定擴展一個責任人域,設置一個負責人維護域 Dutier
14 // 設置責任人字段,通知適配器adapter從 xml中讀取這個屬性,這樣Task對象會擴展出 Dutier屬性,
15 // 注意第二個參數的大小寫與 xml標簽相同
16 adapter.addTaskProperty( "Dutier","DUTIER" ,SFDataRender.types.String);
17 // 第二步:用setTaskField函數來設置責任人甘特屬性域,域顯示方式 headstyle,bodystyle ,inputstyle可使用樣式表,支持更靈活的顯示方式
18 var field1= new SFGanttField({width:100,bodyData:'Dutier' ,inputData:'Dutier',headText: '負責人',headStyle:{textAlign:'left' },bodyStyle: {textAlign:'right'}})
19 SFGanttField.setTaskField( "Dutier",field1);
20
21 // 修改已有甘特域的顯示屬性和輸入屬性
22 SFGanttField.getTaskField( "OutlineNumber").setHeadText("WBS" ); // 設置顯示方式
23 SFGanttField.getTaskField( "Start").setInputHandle(InputHandle_DateTime); // 設置開始日期輸入方式
24 SFGanttField.getTaskField( "Finish").setInputHandle(InputHandle_DateTime); // 設置結束日期輸入方式
25 // 設置甘特圖顯示字段屬性
26 gtConfig.setConfig( "SFGantt/taskFieldNames","StatusIcon,Name,Start,Finish,Duration,Dutier,OutlineNumber" ); // 設置甘特圖顯示的字段列表
27
28 // 初始化甘特圖數據對象
29 gtData= new SFData(adapter);
30 // 初始化甘特圖日志對象,初始化日志對象后,系統才會記錄修改日志,用於向后台發送修改內容。設置記錄日志內容
31 gtLog= new SFDataLogging(gtData);
32 gtLog.setTaskFields( "Name,Start,Finish,Summary,PercentComplete,Dutier,Notes" )
33
34
35 // 添加插件
36 // 添加大綱級別插件
37 gtData.addComponent( new SFDataOutlineComponent()); // 使用向日葵甘特SFDataOutlineComponent數據插件
38
39 // 根據配置和數據產生甘特數據
40 gtMap= new SFGantt(gtConfig,gtData);
41
42 // 設置甘特圖的事件
43 // 增加甘特圖事件SFEvent.addListener
44 // 第一個參數為 gantt數據 gtData
45 // 第二個參數為事件名稱
46 // 第三個參數為事件激發時的調用函數
47 SFEvent.addListener(gtData, "aftertaskadd",onAfterTaskAdd); // 添加任務之后調用事件產生唯一順序號 guid
48 SFEvent.addListener(gtData, "afterlinkadd",onAfterLinkAdd); // 添加鏈接之后調用事件產生唯一順序號 guid
49 SFEvent.addListener(gtData, "aftertaskchange",onAfterTaskChange); // 任務屬性賦值事件
50 SFEvent.addListener(gtMap, "linkclick",onLinkdblClick); // 鏈接線點擊事件任務屬性賦值事件
51 // 計算所有任務的工期,任務都按照固定工期進行運算。
52 initDuration();
53 /* gtMap.addControl(aaa=new SFGanttProgressLine("2009-12-02 18:00:00",{
54 vertexImg:' http://www.51diaodu.cn/sfgantt/img/task_head_20.gif ',
55 vertexSize:[10,10],
56 vertexStyle:{border:'solid 1px green'},
57 lineColor:'black',
58 lineWeight:1
59 })); */
60
61 // 增加項目進度線
62 pgl= new SFGanttProgressLine("2004-12-02 18:00:00" );
63 gtMap.addControl(pgl);
64
65 // 甘特圖顯示,第一個參數用於甘特圖初始化顯示時的 左邊界,第二個參數用於顯示比例
66 gtMap.showMap(SFGlobal.getDate( "2009-11-18 00:00:00"),4);
67
68
69 }
70
71
72 function save()
73 {
74
75 var xmlDom=gtLog.getXml(); // 獲得更新記錄的XML文件
76 var strLog=SFAjax.getXmlString(xmlDom);
77 alert( "發送到后台的更改記錄為:\n" +strLog);
78 var params=[];
79 // 在這里計算出此任務的順序
80 params.push( "action=save");
81 params.push( "t="+ new Date().valueOf());
82 params.push( "uid="+projectUid);
83
84 SFAjax.loadXml("servlet/dataResolver?" +params.join("&"), function(doc)
85 {
86 if(doc.documentElement.getAttribute("errorCode" )=="0")
87 {
88 gtLog.clear(); // 如果存盤成功,就重置所有變更信息
89 alert( "數據保存成功!" );
90 }
91 else
92 {
93 alert( "?"+params.join("&" ));
94 alert(doc.documentElement.firstChild?doc.documentElement.firstChild.nodeValue:"未知錯誤");
95 }
96
97
98 }, false,strLog);
99
100 }
xml與數據庫交互如下圖所示
與數據庫交互的關鍵是
SFDataLogging對象,該對象可監視甘特圖頁面修改操作,並在保存時向后台發送相關修改命令。后台servlet解析該命令並進行相關操作並保存數據到數據庫。
以上只是基本操作,我拋磚引玉下,具體讀者可參閱API文檔和實例程序,網址如下:
http://www.51diaodu.cn/sfgantt/examples/index.html