SVGGraph Gantt Charts

« Return to SVGGraph page

Skip to:

Page 2:

A Gantt chart is a type of horizontal floating bar graph, used for showing the schedule and progress of a project. Each bar represents a task, and these tasks can be grouped together to show sub-projects. The chart can also show milestones - markers that show imprtant points in the project. The graph type name that you should use to make SVGGraph render these is "GanttChart".

Gantt charts are quite complicated, so to organise this a bit better I have spread the information across two pages. The most common options are explained on this page, with advanced topics and the lists of options and structured data fields on the second page.

Full example

Before I explain how to use GanttChart, here is an example showing a main project broken down into two sub-projects, with four tasks and a milestone.

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022Big projectFirst partA simple taskSecond taskSecond partImportant dateThird taskFinal task[36.8%][57.93%][80%][40%][7.62%]Important date[10%][0%]
Gantt chart

The task bars are standard floating bar chart bars, though they do show the percentage completion as a gauge in the filled area. Group bars are displayed with downward points at each end, and these too show the percentage completion inside. Milestones are displayed as diamond-shaped markers, and the lines with arrow heads display dependencies between tasks.

There are plenty of options for configuring Gantt charts, though the task bars, milestones and group bars are all specified using structured data.

Automatic height

One important change for Gantt charts is the added support for an automatic SVG document height. Supplying the string "auto" as the graph height will make SVGGraph calculate a height for the graph based on the number of entries, font sizes, bar widths and other options.

$graph = new Goat1000\SVGGraph\SVGGraph(670, 'auto', $options);

You can continue to specify your own height for the graph and the bars and milestone markers will be spread out or squashed together to fit the available space.

Task bars

The simplest Gantt chart contains only task bars. For this example I have set the bar_round option to 10, rounding off the ends of the bars.

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022A simple taskSecond taskThird taskFinal task
Gantt chart, task bars only

Since Gantt charts require more than simple coordinate pairs, you must use structured data for passing the bar values to SVGGraph:

$options = [
  'structure' => [
    'key' => 0, 'value' => 1, 'end' => 2,
  ],
  'bar_round' => 10,
];

$values = [
  ['A simple task', '2022-04-01', '2022-04-13'],
  ['Second task', '2022-04-05', '2022-04-20'],
  ['Third task', '2022-05-02', '2022-05-17'],
  ['Final task', '2022-05-16', '2022-05-20'],
];

The example is using the task names as the key field, with the value field and end field containing the start and end dates of the tasks.

Repeated item names

If you want to repeat the name of a task, group or milestone, you must use a separate unique key field and the axis_text field:

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022A simple taskTestingSecond taskTestingFinal taskTesting
Gantt chart with repeated tasks

In this example “Testing” appears twice, so I have had to use a key field:

$options = [
  'structure' => [
    'key' => 0, 'axis_text' => 1, 'value' => 2, 'end' => 3,
  ],
  'bar_round' => 10,
];

$values = [
  ['A0', 'A simple task', '2022-04-01', '2022-04-13'],
  ['A2a', 'Testing', '2022-04-13', '2022-04-15'],
  ['A1', 'Second task', '2022-04-05', '2022-04-20'],
  ['A2', 'Testing', '2022-04-20', '2022-04-21'],
  //['A3', 'Third task', '2022-05-02', '2022-05-17'],
  ['A4', 'Final task', '2022-05-16', '2022-05-20'],
  ['A5', 'Testing', '2022-05-20', '2022-05-20'],
];

I have used alphanumeric string keys for this example because it allows me to comment out one of the values. If I had used numeric keys and commented one out there would have been a gap in the chart where the missing item should be. Apart from that, numeric keys should work fine - just make sure that the key values are sequential integers starting at 0.

Completion percentages

To show how far the project has progressed you can give each task a completion percentage.

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022A simple taskTestingSecond taskTestingThird taskFinal taskTesting[50%][0%][20%][0%][60%][78%][0%]
Gantt chart with completion percentages

To do this I added a complete field to the data structure and set the colour used for the complete part. SVGGraph uses the dataset 0 colour for incomplete bars and the dataset 1 colour for the complete gauge inside the bar:

$options = [
  'structure' => [
    'key' => 0, 'axis_text' => 1, 'value' => 2, 'end' => 3,
    'complete' => 'c',
  ],
  'bar_round' => 10,
  'show_data_labels' => true,
  'pad_right' => 20,
];

$values = [
  ['A0', 'A simple task', '2022-04-01', '2022-04-13', 'c' => 50],
  ['A2a', 'Testing', '2022-04-13', '2022-04-15'],
  ['A1', 'Second task', '2022-04-05', '2022-04-20', 'c' => 20],
  ['A2', 'Testing', '2022-04-20', '2022-04-21'],
  ['A3', 'Third task', '2022-05-02', '2022-05-17', 'c' => 60],
  ['A4', 'Final task', '2022-05-16', '2022-05-20', 'c' => 78],
  ['A5', 'Testing', '2022-05-20', '2022-05-20'],
];

// orange-red-purple range for bars, green-blue for complete
$graph->colourRangeHexHSL(0, '#c50', '#c59');
$graph->colourRangeHexHSL(1, '#6a0', '#6a9');

The complete field is set to "c" to use the relevant parts of the data array. I've also enabled data labels, which display the completion percentage. The extra pad_right is there to provide a bit more space for the labels.

Milestones

A Gantt chart with nothing but milestones seems a bit odd, but SVGGraph does support doing that. Here is what it can look like:

02 May09 May16 May23 May30 May2022Start hereMilestone 2Milestone 3AnotherAnotherLast oneStart hereMilestone 2Milestone 3AnotherAnotherLast one
Gantt chart with milestones only

The milestone field is set in the structure to use the "m" values from the data. These are simple booleans to tell SVGGraph that the row of data represents a milestone. Milestones are points in time, so the end value is not used or required.

$options = [
  'structure' => [
    'key' => 0, 'axis_text' => 1, 'value' => 2, 'end' => 3,
    'milestone' => 'm',
  ],
  'show_data_labels' => true,
];

$values = [
  ['M1', 'Start here', '2022-05-02', 'm' => true],
  ['M2', 'Milestone 2', '2022-05-09', 'm' => true],
  ['M3', 'Milestone 3', '2022-05-16', 'm' => true],
  ['M4', 'Another', '2022-05-17', 'm' => true],
  ['M5', 'Another', '2022-05-18', 'm' => true],
  ['M6', 'Last one', '2022-06-02', 'm' => true],
];

The show_data_labels option is used again to label the milestones on the chart. There are options for setting the colour, size and marker type used for the milestones, but I haven't used any here.

Multiple task bars/milestones

It is possible to show multiple task bars or milestones on a single row of the Gantt chart, or even a mixture of the two. You can do this by using multiple datasets for your task bars and milestones.

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022A simple taskTestingSecond taskTestingThird taskFinal taskTesting[50%][0%][20%][0%][60%][78%][0%][25%][0%]Test 1A simple taskOKTest 2
Gantt chart with multiple task bars/milestones

The structure for this example is a bit more complicated than most, so I have lined up the numbered fields in the data array to make it a bit clearer:

$options = [
  'auto_fit' => true,
  'structure' => [
    'key' => 0, 'axis_text' => 1,
    'value' => [2, 4, 6, 8, 10],
    'end' => [3, 5, 7, 9, 11],
    'complete' => ['c1', 'c2', 'c3', 'c4', 'c5'],
    'milestone' => ['m1', 'm2', 'm3', 'm4', 'm5'],
    'label' => ['l1', 'l2', 'l3', 'l4', 'l5'],
  ],
];

$values = [
//  0    1                2             3             4             5             6
  ['A0', 'A simple task', '2022-04-01', '2022-04-13', '2022-05-01', '2022-05-15', '2022-04-20',
  'c1' => 50, 'c2' => 25, 'm3' => true],
  ['A2a', 'Testing',      '2022-04-13', '2022-04-15', '2022-05-15', '2022-05-17', '2022-05-21',
  'm3' => true, 'l3' => 'OK'],
  ['A1', 'Second task',   '2022-04-05', '2022-04-20',
  'c1' => 20],
  ['A2', 'Testing',       '2022-04-20', '2022-04-21'],
  ['A3', 'Third task',    '2022-05-02', '2022-05-17',
  'c1' => 60],
  ['A4', 'Final task',    '2022-05-16', '2022-05-20',
  'c1' => 78],
  ['A5', 'Testing',       '2022-05-20', '2022-05-20', '2022-04-05', null,         '2022-04-19',
  'm2' => true, 'm3' => true, 'l2' => 'Test 1', 'l3' => 'Test 2'],
];

The data fields 0 and 1 are the key field and axis text, as in the previous example. Instead of a single value and end field there are now up to five of each. Because there are multiple bars there must also be multiple complete fields, one for each bar. I have also added multiple label fields to allow each bar or milestone to have its own label.

The milestones are enabled with the five fields m1 to m5. I've chosen the names of these fields so that m3 being true means that the third value field is a milestone, etc. If you prefer, you could name all the fields, or even not name any and just rely on the numeric index.

Bar/milestone order and overlapping

Note that the two milestones on the bottom row of the graph have dates before the task bar that comes before them in the data. SVGGraph does not do anything to prevent bars and milestones from overlapping, so you could position milestones on top of bars, or vice-versa if that is what you want. The bars and milestones are drawn in order of dataset, not in date order.

Group bars

Group bars are used to group multiple task bars and milestones together. They usually have downward-pointing corners at either end.

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022A Group barA simple taskTestingSecond taskTestingThird taskFinal taskTesting[28.53%][50%][0%][20%][0%][60%][78%][0%]
Gantt chart with group bar

This example sets the group field in the structure to point at the "g" fields in the data array. There is only one group defined, with a value of 4, and that means the four entries following the group are included in the group.

$options = [
  'structure' => [
    'key' => 0, 'axis_text' => 1, 'value' => 2, 'end' => 3,
    'complete' => 'c',
    'group' => 'g',
  ],
  'bar_round' => 10,
  'show_data_labels' => true,
  'pad_right' => 20,
];

$values = [
  ['G0', 'A Group bar', 'g' => 4],
  ['A0', 'A simple task', '2022-04-01', '2022-04-13', 'c' => 50],
  ['A2a', 'Testing', '2022-04-13', '2022-04-15'],
  ['A1', 'Second task', '2022-04-05', '2022-04-20', 'c' => 20],
  ['A2', 'Testing', '2022-04-20', '2022-04-21'],
  ['A3', 'Third task', '2022-05-02', '2022-05-17', 'c' => 60],
  ['A4', 'Final task', '2022-05-16', '2022-05-20', 'c' => 78],
  ['A5', 'Testing', '2022-05-20', '2022-05-20'],
];

If you want to include all the following entries in the group, you could use a larger number, or instead of a number use the string "*". In fact, any non-numeric string would work, since strings are used for nested group levels.

The completion gauge inside the group bar is automatically calculated from all the bars inside the group, so you don't need to do anything to make it work.

Nested groups

To put groups inside other groups is quite easy - just pick a name for each level and use it as the value of the group field.

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022Top-level groupSub-group 1A simple taskTestingSecond taskTestingSub-group 2Third taskFinal taskTesting[41.43%][28.53%][50%][0%][20%][0%][61.36%][60%][78%][0%]
Gantt chart with group and sub-groups

This example has one top-level group and two sub-groups. The field structure is the same in this example, but the data values have changed:

$values = [
  ['G0', 'Top-level group', 'g' => 'top'],
  ['G1', 'Sub-group 1', 'g' => 'level 1'],
  ['A0', 'A simple task', '2022-04-01', '2022-04-13', 'c' => 50],
  ['A2a', 'Testing', '2022-04-13', '2022-04-15'],
  ['A1', 'Second task', '2022-04-05', '2022-04-20', 'c' => 20],
  ['A2', 'Testing', '2022-04-20', '2022-04-21'],
  ['G2', 'Sub-group 2', 'g' => 'level 1'],
  ['A3', 'Third task', '2022-05-02', '2022-05-17', 'c' => 60],
  ['A4', 'Final task', '2022-05-16', '2022-05-20', 'c' => 78],
  ['A5', 'Testing', '2022-05-20', '2022-05-20'],
];

The “Top-level group” group has a group value of "top", which is just an arbitrary name for that level. The two sub-groups have a group value of "level 1", another arbitrary name.

SVGGraph puts every task bar or milestone below a named group into that group. When it finds a new group name it starts a new sub-group. A group ends when the data contains the same group name again, starting a new group at the same level.

Writing that out makes it sound really complicated - here's another example, this time with a top level, sub-level and sub-sub-level:

28 Mar04 Apr11 Apr18 Apr25 Apr02 May09 May16 May2022Top-level groupSub-group 1A simple taskTestingSub-sub-groupSecond taskTestingSub-group 2Third taskSub-sub-groupFinal taskTesting[41.43%][28.53%][50%][0%][17.78%][20%][0%][61.36%][60%][65%][78%][0%]
Gantt chart with three levels of groups

And here is the data for it, with the rows indented to match the chart:

$values = [
  ['G0', 'Top-level group', 'g' => 'top'],
    ['G1', 'Sub-group 1', 'g' => 'level 1'],
      ['A0', 'A simple task', '2022-04-01', '2022-04-13', 'c' => 50],
      ['A2a', 'Testing', '2022-04-13', '2022-04-15'],
      ['G1a', 'Sub-sub-group', 'g' => 'l 2'],
        ['A1', 'Second task', '2022-04-05', '2022-04-20', 'c' => 20],
        ['A2', 'Testing', '2022-04-20', '2022-04-21'],
    ['G2', 'Sub-group 2', 'g' => 'level 1'],
      ['A3', 'Third task', '2022-05-02', '2022-05-17', 'c' => 60],
      ['G2a', 'Sub-sub-group', 'g' => 'l 2'],
        ['A4', 'Final task', '2022-05-16', '2022-05-20', 'c' => 78],
        ['A5', 'Testing', '2022-05-20', '2022-05-20'],
];

There is one top-level group called "top", containing everything else because the group name "top" doesn't come up again.

“Sub-group 1” is called "level 1" and contains everything until the name "level 1" is used again for “Sub-group 2”.

The name "l 2" is used for the sub-sub-group inside "level 1". It is not repeated inside the parent group, so it ends when its parent group ends.

« Back to top of page Gantt charts, continued »

This site uses cookies - details here.