Макет Gantt

Начиная с версии 5.0, Gantt поддерживает настраиваемый макет, который позволяет размещать элементы компонента как внутренние представления внутри макета. Эта функция позволяет добавлять дополнительные временные шкалы и гриды, создавая гибкую структуру диаграммы Gantt с различными способами организации её частей.

Например, вы можете добавить дополнительный грид справа от временной шкалы:

Related sample:  Grid columns rightside of gantt

Или разместить ещё один грид и временную шкалу под основными.

Related sample:  Gantt chart with resource panel

Макет по умолчанию

Макет управляется через настройку gantt.config.layout. Вот конфигурация макета по умолчанию:

gantt.config.layout = {
    css: "gantt_container",
    rows:[
        {
           cols: [
            {
              // основное представление грида   
              view: "grid",  
              scrollX:"scrollHor", 
              scrollY:"scrollVer"
            },
            { resizer: true, width: 1 },
            {
              // основное представление временной шкалы
              view: "timeline", 
              scrollX:"scrollHor", 
              scrollY:"scrollVer"
            },
            {
              view: "scrollbar", 
              id:"scrollVer"
            }
        ]},
        {
            view: "scrollbar", 
            id:"scrollHor"
        }
    ]
}

Макет Gantt состоит из ячеек, заполненных представлениями. Эти представления отображают основные и вспомогательные элементы Gantt, такие как:

  • grid - грид диаграммы Gantt. Основной грид для отображения задач имеет id:"grid";
  • timeline - временная шкала диаграммы Gantt. Основная временная шкала для задач имеет id:"timeline";
  • resizer - линия-разделитель. Для активации установите свойство resizer в true. Доступно только в PRO-редакции;
  • scrollbar - скроллбары, используемые в диаграмме Gantt. Представления грида и временной шкалы могут быть связаны с определёнными скроллбарами (подробнее ниже).
  • resourceGrid - преднастроенный грид для панели ресурсов. Доступно только в PRO-редакции. Подробнее здесь.
  • resourceTimeline - преднастроенная временная шкала для панели ресурсов. Доступно только в PRO-редакции. Подробнее здесь.

Каждое представление настраивается через объект с соответствующими свойствами. Вы можете настроить параметры для представлений grid и timeline. По умолчанию параметры берутся из глобального объекта gantt.config.

Учтите, что конфигурацию макета необходимо задавать до инициализации Gantt. Если вы изменяете макет после, обновите его с помощью resetLayout.

Скроллбар

Скроллбары в макете определяются представлением "scrollbar". Можно использовать как горизонтальные, так и вертикальные скроллбары.

Чтобы добавить скроллбар, свяжите его с нужным представлением, указав в свойствах scrollX или scrollY id скроллбара.

Привязка скроллбара к представлению

Несколько представлений могут использовать один и тот же скроллбар. Для связывания представления со скроллбаром:

  • определите скроллбар с нужным направлением прокрутки и задайте ему ID
  • укажите этот ID в свойстве scrollX или scrollY нужного представления

Размещение скроллбара внутри массива cols создаёт вертикальный скроллбар, а внутри массива rows — горизонтальный. Также можно явно указать направление прокрутки с помощью свойства scroll:

{ view: "scrollbar", id:"scroller", scroll: "x" } // горизонтальный

или:

{ view: "scrollbar", id:"scroller", scroll: "y" } // вертикальный

Вот пример привязки пользовательских представлений грида и временной шкалы к вертикальному скроллбару:

gantt.config.layout = {
    css: "gantt_container",
    rows:[
        {
           cols: [
            {             
              view: "grid", 
              scrollY:"scrollVer"
            },
            { resizer: true, width: 1 },
            {
              view: "timeline", 
              scrollY:"scrollVer"
            },
            {
              view: "scrollbar", 
              id:"scrollVer"
            }
        ]}
    ]
}

Прокрутка вертикального скроллбара будет перемещать одновременно грид и временную шкалу. В стандартном макете представления грида и временной шкалы связаны как с горизонтальным, так и с вертикальным скроллбарами.

Также можно задать отдельный горизонтальный скроллбар только для грида. Подробнее в соответствующем разделе.

Скроллбары для представления

Ранее мы рассмотрели, как добавить один скроллбар к представлению с помощью простой конфигурации макета, например:

{cols: [ {rows: [{}, {}]}, {rows: [{}, {}]}]}

или

{rows: [ {cols: [{}, {}]}, {cols: [{}, {}]}]}

Если вы хотите связать представление и с вертикальным, и с горизонтальным скроллбаром, потребуется более сложный макет с несколькими уровнями вложенности cols и rows, например:

{cols: [ 
    {
        rows: [
            {
                cols: [{}, {}]
            }, 
            {
                cols: [{}, {}]
            }
        ]
    }, 
    {
        rows: [
            {
                cols: [{}, {}]
            }, 
            {
                cols: [
                    {
                        rows: [{}, {}]
                    }, 
                    {   
                        rows: [{}, {}]
                    }
                ]
            }
        ]
    }
]}

Посмотрите эти примеры:

Настройка макета

Вы можете изменить макет по умолчанию и задать схему, которая соответствует вашим требованиям, добавляя дополнительные представления в диаграмму Gantt.

Например, чтобы создать панель ресурсов под основной диаграммой Gantt с дополнительными представлениями грида и временной шкалы, выполните следующие шаги:

  • создайте макет с несколькими строками
  • разместите основной грид и временную шкалу в первой строке
  • добавьте дополнительный грид и временную шкалу во вторую строку, связав их с пользовательским источником данных
  • вставьте разделитель между строками
  • добавьте скроллбар для последней строки и свяжите его с обеими временными шкалами (основной и ресурсной)

Пример конфигурации:

gantt.config.layout = {
    css: "gantt_container",
    rows:[
        {
          // макет по умолчанию
          cols: [
            {view: "grid",
                config: mainGridConfig, scrollY:"scrollVer"},
            {resizer: true, width: 1},
            {view: "timeline", 
                scrollX:"scrollHor", scrollY:"scrollVer"},
            {view: "scrollbar", id:"scrollVer"}
          ]
        },
        {resizer: true, width: 1},
        {
          // пользовательский макет
          cols: [
            {view: "grid", id: "resourceGrid", bind:"resource", 
                config:resourceGridConfig, scrollY:"resourceVScroll"},
            {resizer: true, width: 1},
            {view:"timeline", id:"resourceTimeline", scrollX:"scrollHor", 
                bind:"resource", bindLinks: null, layers: resourceLayers, 
                scrollY:"resourceVScroll"},
            {view: "scrollbar", id:"resourceVScroll"}
          ]
        },
        {view: "scrollbar", id:"scrollHor"}
    ]
};

В этом примере дополнительный грид отображает ресурсы и их загрузку, а дополнительная временная шкала показывает распределение рабочих часов по месяцам с выделением стандартных и сверхурочных часов.

Свойства пользовательских grid и timeline

Пользовательские представления grid и timeline содержат дополнительные свойства:

Для grid и timeline

  • bind - (string) указывает ID источника данных, из которого брать данные (например, "resource" в примере)

Для timeline

  • bindLinks - (string) указывает источник связей; установите null, если связанных связей нет
  • layers - (array) набор функций addLayer(), определяющих стиль отображения данных

Добавление хранилища данных для пользовательских представлений

Чтобы заполнить пользовательские представления нужными данными, необходимо добавить отдельное хранилище данных. Создание нового хранилища выполняется с помощью метода
createDatastore, где вы указываете конфигурацию хранилища данных:

var resourcesStore = gantt.createDatastore({
    name:"resource",
    initItem: function(item){
        item.id = item.key || gantt.uid();
        return item;
    }
});

В этом примере создаётся хранилище данных с именем "resource".

Для загрузки данных из хранилища в пользовательские представления используется метод parse:

resourcesStore.parse([// resources
    {key:'0', label: "N/A"},
    {key:'1', label: "John"},
    {key:'2', label: "Mike"},
    {key:'3', label: "Anna"}
]);

Чтобы получить объект конфигурации определённого хранилища данных, используйте метод getDatastore:

var tasksStore = gantt.getDatastore("task");

Этот метод принимает имя хранилища данных в качестве параметра.

При использовании встроенных представлений ресурсов Gantt может создавать хранилище данных автоматически. Подробнее здесь.

Динамическое отключение/включение разделителей

Иногда требуется динамически отключать разделители между ячейками Gantt. Самый простой способ сделать это — скрыть их с помощью CSS.

Вы можете использовать такое CSS-правило:

.no_resizers .gantt_resizer{
    display:none;
}

Далее добавьте этот класс к контейнеру Gantt, чтобы скрыть разделители:

gantt.$container.classList.add("no_resizers");

Чтобы вернуть разделители, просто удалите класс:

gantt.$container.classList.remove("no_resizers");

HTML как внутреннее представление

Пользовательский HTML также может использоваться в качестве внутренних представлений внутри макета Gantt. Пример:

gantt.config.layout = {
 css: "gantt_container",
  rows: [
    {
      cols: [
        {view: "grid",scrollX: "scrollHor", scrollY: "scrollVer"},
        { html:"<div class='custom-content'>custom content</div>", 
            css:"custom-content", width:50},
        {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
        { html:"<div class='custom-content'>custom content</div>", 
            css:"custom-content", width:50},
        {view: "scrollbar", id: "scrollVer"}
      ]
    },
    {view: "scrollbar", scroll: "x", id: "scrollHor"}
 ]
}

Обязательные представления и настройки

Публичный API объекта gantt включает методы, связанные с определёнными представлениями макета, такими как getTaskPosition, getTaskNode и getScrollState.

Для корректной работы этих методов макет должен включать стандартные грид, временную шкалу, полосы прокрутки, и Gantt должен иметь возможность их найти. Это достигается назначением определённых id стандартным представлениям:

gantt.config.layout = {
 css: "gantt_container",
  rows: [
  {
   cols: [
    {view: "grid", id: "grid", scrollX: "scrollHor", scrollY: "scrollVer"},
    {view: "timeline", id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
    {view: "scrollbar", id: "scrollVer"}
   ]
  },
  {view: "scrollbar", id: "scrollHor"}
 ]
};

Обязательные представления и их id:

  • view: "grid", id: "grid"
  • view: "timeline", id: "timeline"
  • view: "scrollbar", id: "scrollHor"
  • view: "scrollbar", id: "scrollVer"

Если id не задан, Gantt либо использует имя представления в качестве id по умолчанию, либо сгенерирует уникальный автоматически. Поэтому для стандартных грид и timeline параметр "id" можно не указывать:

gantt.config.layout = {
 css: "gantt_container",
  rows: [
  {
   cols: [
    {view: "grid", scrollX: "scrollHor", scrollY: "scrollVer"},
    {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
    {view: "scrollbar", id: "scrollVer"}
   ]
  },
  {view: "scrollbar", id: "scrollHor"}
 ]
};

Вы можете добавить любое количество дополнительных представлений в макет.

Конфигурация и шаблоны представлений

Грид и Timeline используют шаблоны и конфигурацию из глобальных gantt.config/gantt.templates. Однако их можно переопределить для конкретных представлений на уровне макета.

Например:

var secondGridColumns = {
  columns: [
    {
        name: "status", label: "Status", width: 60, align: "center", 
        template: function (task) {
            var progress = task.progress || 0;
            return Math.floor(progress * 100) + "";
        }
    },
    {
        name: "impact", width: 80, label: "Impact", template: function (task) {
            return (task.duration * 1000).toLocaleString("en-US", {
              style: 'currency', currency: 'USD'
          });
        }
    }
  ]
};
 
gantt.config.layout = {
  css: "gantt_container",
  rows: [
    {
      cols: [
        {view: "grid", id: "grid", width: 320, scrollY: "scrollVer"},
        {resizer: true, width: 1},
        {view: "timeline", id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
        {resizer: true, width: 1},
        {view: "grid", width: 120, bind:"task", 
            scrollY:"scrollVer", config:secondGridColumns},           {view: "scrollbar", scroll: "y", id: "scrollVer"}
      ]
    },
    {view: "scrollbar", id: "scrollHor", height: 20}
  ]
};

Представления также могут наследовать конфигурацию и шаблоны от родительского макета:

var resourceConfig = {        scale_height: 30      };                         
gantt.config.layout = {
  css: "gantt_container",
  rows: [
    {
      cols: [
        {view: "grid", group:"grids", scrollY: "scrollVer"},
        {resizer: true, width: 1},
        {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
        {view: "scrollbar", id: "scrollVer", group:"vertical"}
      ],
      gravity:2
    },
    {resizer: true, width: 1},
    {
      config: resourceConfig,         cols: [
        {view: "resourceGrid", group:"grids", width: 435, scrollY: "resourceVScroll" },
        {resizer: true, width: 1},
        {view: "resourceTimeline", scrollX: "scrollHor", scrollY: "resourceVScroll"},
        {view: "scrollbar", id: "resourceVScroll", group:"vertical"}
      ],
      gravity:1
    },
    {view: "scrollbar", id: "scrollHor"}
  ]
};

Более подробную информацию смотрите в статье Resource Management.

Группы видимости

Иногда бывает полезно синхронизировать видимость определённых элементов макета. Например, если есть горизонтальные полосы прокрутки в соседних ячейках, возможно, вы захотите, чтобы обе отображались или скрывались одновременно.

Related sample:  Horizontal scroll inside Grid


Другой пример — несколько гридов в разных строках временной шкалы, которые должны иметь одинаковую ширину. Когда один грид изменяет размер, другие также должны подстраиваться.

Related sample:  Resource load diagram

Обе эти задачи решаются с помощью свойства group в представлении. Это свойство принимает любую строку, и представления с одинаковым значением group будут синхронизированы.

  • Для полос прокрутки это означает, что их видимость связана: если одна из полос в группе видима, видимыми будут все.
  • Для других ячеек это обеспечивает одинаковую ширину или высоту в зависимости от макета.

Пример синхронизации видимости полос прокрутки:

gantt.config.layout = {
  css: "gantt_container",
  cols: [
    {
       width:400,
       minWidth: 200,
       maxWidth: 600,
       rows:[
         {view: "grid", scrollX: "gridScroll", scrollable: true, scrollY: "scrollVer"},
         {view: "scrollbar", id: "gridScroll", group:"horizontal"}            ]
    },
    {resizer: true, width: 1},
    {
      rows:[
        {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
        {view: "scrollbar", id: "scrollHor", group:"horizontal"}            ]
    },
    {view: "scrollbar", id: "scrollVer"}
  ]
};

Пример синхронизации ширины гридов:

gantt.config.layout = {
  css: "gantt_container",
  rows: [
    {
      cols: [
        {view: "grid", group:"grids", scrollY: "scrollVer"},
        {resizer: true, width: 1},
        {view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
        {view: "scrollbar", id: "scrollVer", group:"vertical"}          ],
      gravity:2
    },
    {resizer: true, width: 1},
    {
      config: resourceConfig,
      cols: [
        {view: "resourceGrid", group:"grids", width: 435, scrollY: "resourceVScroll" },
        {resizer: true, width: 1},
        {view: "resourceTimeline", scrollX: "scrollHor", scrollY: "resourceVScroll"},
        {view: "scrollbar", id: "resourceVScroll", group:"vertical"}         ],
      gravity:1
    },
    {view: "scrollbar", id: "scrollHor"}
  ]
};

Размеры частей макета Gantt

Относительные размеры ячеек макета Gantt можно управлять с помощью свойства gravity в конфигурации каждой ячейки. Это значение определяет пропорцию размеров между ячейками.

gantt.config.layout = {
    css: "gantt_container",
    rows: [
        {
            cols: [
                // columns config
            ],
            gravity:2             },
        { resizer: true, width: 1 },
        {
            config: resourceConfig,
            cols: [
                // columns config
            ],
            gravity:1               },
    {view: "scrollbar", id: "scrollHor"}
    ]
};

В этом примере Gantt и диаграмма ресурсов делят пространство в пропорции 2:1. То есть, Gantt занимает примерно 66%, а диаграмма ресурсов — около 33%. Использование пропорции 1:1 разделит пространство поровну.

Минимальная/максимальная ширина/высота ячейки

Чтобы ограничить размер частей макета при изменении размера, используйте свойства minWidth/maxWidth для ячеек внутри массива cols. Аналогично, minHeight/maxHeight можно задать для ячеек в массиве rows для ограничения высоты.

Пример использования minWidth/maxWidth в конфигурации колонок:

gantt.config.grid_elastic_columns = true;
 
gantt.config.layout = {
  css: "gantt_container",
  cols: [
    {
      width: 400,
      minWidth: 200,       maxWidth: 600,       rows: [
        {
          view: "grid", scrollable: true, scrollX: "scrollHor1", scrollY: "scrollVer"
        },
        {
          view: "scrollbar", id: "scrollHor1", scroll: 'x', group: 'hor'
        },
      ]
    },
    { resizer: true, width: 1 },
    {
      rows: [
        {
          view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"
        },
        {
          view: "scrollbar", id: "scrollHor", scroll: 'x', group: 'hor'
        },
      ]
    },
    {
      view: "scrollbar", id: "scrollVer"
    }
  ]
}

Скрытие родительских представлений макета

Если нужно скрыть представление макета при скрытии всех его дочерних представлений, задайте hide_empty:true в конфигурации этой ячейки макета, например:

gantt.config.layout = {
    css: "gantt_container",
    cols: [
        {
            hide_empty: true,             rows:[
                {view: "grid"}
            ]
        },
        {resizer: true},
        {
            hide_empty: true,             rows:[
                {view: "timeline"}
            ]
        }
    ]
};

Related sample:  Скрытие grid/timeline представлений

Переключение между представлениями

Для переключения между разными представлениями макета смотрите разделы Решения: Переключение grid/диаграммы и Решения: Переключение представления ресурсов.

Заморозка колонок в grid-представлении

Можно инициализировать Gantt с одной или несколькими замороженными колонками. Инструкции по этому вопросу смотрите в разделе Решения: Как заморозить/зафиксировать колонки в grid.

К началу