Zooming Functionality in React Gantt Chart Component
12 Jan 202624 minutes to read
The React Gantt Chart component provides zooming support to adjust the timeline view dynamically. This includes increasing or decreasing the width of timeline cells and changing the timeline units to view tasks across various timespan from minutes to decades.
To enable zooming features, add ZoomIn, ZoomOut, and ZoomToFit to the toolbar items collection. These actions can also be triggered externally using the built-in methods like zoomIn, zoomOut, and fitToProject.
Zoom in
This support is used to increase the timeline width and timeline unit from years to minutes timespan. When the ZoomIn icon was clicked, the timeline cell width is increased when the cell size exceeds the specified range and the timeline unit is changed based on the current zoom levels.
Zoom out
This support is used to increase the timeline width and timeline unit from minutes to years timespan. When the ZoomOut icon was clicked, the timeline cell width is decreased when the cell size falls behind the specified range and the timeline view mode is changed based on the current zooming levels.
Zoom to fit
This support is used to view all the tasks available in a project within available area on the chart part of Gantt. When users click the ZoomToFit icon, then all the tasks are rendered within the available chart container width.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, ColumnsDirective, ColumnDirective, Inject } from '@syncfusion/ej2-react-gantt';
import { Edit, Toolbar, Selection } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
const taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const toolbar = ['ZoomIn', 'ZoomOut', 'ZoomToFit'];
return (
<GanttComponent
height="430px"
dataSource={data}
taskFields={taskSettings}
toolbar={toolbar}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="150" />
<ColumnDirective field="StartDate" headerText="Start Date" width="150" />
<ColumnDirective field="Duration" headerText="Duration" width="150" />
<ColumnDirective field="Progress" headerText="Progress" width="150" />
</ColumnsDirective>
<Inject services={[Edit, Toolbar, Selection]} />
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, ColumnsDirective, ColumnDirective, Inject } from '@syncfusion/ej2-react-gantt';
import { Edit, Toolbar, Selection } from '@syncfusion/ej2-react-gantt';
import { TaskFieldsModel } from '@syncfusion/ej2-gantt';
import { data } from './datasource';
function App() {
const taskSettings: TaskFieldsModel = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const toolbar: string[] = ['ZoomIn', 'ZoomOut', 'ZoomToFit'];
return (
<GanttComponent
height="430px"
dataSource={data}
taskFields={taskSettings}
toolbar={toolbar}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="150" />
<ColumnDirective field="StartDate" headerText="Start Date" width="150" />
<ColumnDirective field="Duration" headerText="Duration" width="150" />
<ColumnDirective field="Progress" headerText="Progress" width="150" />
</ColumnsDirective>
<Inject services={[Edit, Toolbar, Selection]} />
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/32.1.19/material.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Customizing zooming levels
Zoom actions are governed by predefined zooming levels specified in the zoomingLevels property. These levels can be customized by assigning a collection of zoom configurations to the zoomingLevels property.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, ColumnsDirective, ColumnDirective, Inject } from '@syncfusion/ej2-react-gantt';
import { Toolbar, Selection, Filter } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
let ganttRef = null;
const taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const toolbar = ['ZoomIn', 'ZoomOut', 'ZoomToFit'];
const customZoomingLevels = [
{
topTier: { unit: 'Month', format: 'MMM, yy', count: 1 },
bottomTier: { unit: 'Week', format: 'dd', count: 1 },
timelineUnitSize: 33, level: 0, timelineViewMode: 'Month', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Month', format: 'MMM, yyyy', count: 1 },
bottomTier: { unit: 'Week', format: 'dd MMM', count: 1 },
timelineUnitSize: 66, level: 1, timelineViewMode: 'Month', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Month', format: 'MMM, yyyy', count: 1 },
bottomTier: { unit: 'Week', format: 'dd MMM', count: 1 },
timelineUnitSize: 99, level: 2, timelineViewMode: 'Month', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Week', format: 'MMM dd, yyyy', count: 1 },
bottomTier: { unit: 'Day', format: 'd', count: 1 },
timelineUnitSize: 33, level: 3, timelineViewMode: 'Week', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Week', format: 'MMM dd, yyyy', count: 1 },
bottomTier: { unit: 'Day', format: 'd', count: 1 },
timelineUnitSize: 66, level: 4, timelineViewMode: 'Week', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Day', format: 'E dd yyyy', count: 1 },
bottomTier: { unit: 'Hour', format: 'hh a', count: 12 },
timelineUnitSize: 66, level: 5, timelineViewMode: 'Day', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Day', format: 'E dd yyyy', count: 1 },
bottomTier: { unit: 'Hour', format: 'hh a', count: 6 },
timelineUnitSize: 99, level: 6, timelineViewMode: 'Day', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
}
];
const onDataBound = () => {
if (ganttRef) {
ganttRef.zoomingLevels = customZoomingLevels;
}
};
return (
<GanttComponent
id="ganttDefault"
height="430px"
dataSource={data}
taskFields={taskSettings}
toolbar={toolbar}
ref={gantt => ganttRef = gantt}
dataBound={onDataBound}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="150" />
<ColumnDirective field="StartDate" headerText="Start Date" width="150" />
<ColumnDirective field="Duration" headerText="Duration" width="150" />
<ColumnDirective field="Progress" headerText="Progress" width="150" />
</ColumnsDirective>
<Inject services={[Toolbar, Selection, Filter]} />
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, ColumnsDirective, ColumnDirective, Inject } from '@syncfusion/ej2-react-gantt';
import { Toolbar, Selection, Filter } from '@syncfusion/ej2-react-gantt';
import { TaskFieldsModel, ZoomTimelineSettings } from '@syncfusion/ej2-gantt';
import { data } from './datasource';
function App() {
let ganttRef: GanttComponent | null = null;
const taskSettings: TaskFieldsModel = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const toolbar: string[] = ['ZoomIn', 'ZoomOut', 'ZoomToFit'];
const customZoomingLevels: ZoomTimelineSettings[] = [
{
topTier: { unit: 'Month', format: 'MMM, yy', count: 1 },
bottomTier: { unit: 'Week', format: 'dd', count: 1 },
timelineUnitSize: 33, level: 0, timelineViewMode: 'Month', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Month', format: 'MMM, yyyy', count: 1 },
bottomTier: { unit: 'Week', format: 'dd MMM', count: 1 },
timelineUnitSize: 66, level: 1, timelineViewMode: 'Month', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Month', format: 'MMM, yyyy', count: 1 },
bottomTier: { unit: 'Week', format: 'dd MMM', count: 1 },
timelineUnitSize: 99, level: 2, timelineViewMode: 'Month', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Week', format: 'MMM dd, yyyy', count: 1 },
bottomTier: { unit: 'Day', format: 'd', count: 1 },
timelineUnitSize: 33, level: 3, timelineViewMode: 'Week', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Week', format: 'MMM dd, yyyy', count: 1 },
bottomTier: { unit: 'Day', format: 'd', count: 1 },
timelineUnitSize: 66, level: 4, timelineViewMode: 'Week', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Day', format: 'E dd yyyy', count: 1 },
bottomTier: { unit: 'Hour', format: 'hh a', count: 12 },
timelineUnitSize: 66, level: 5, timelineViewMode: 'Day', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
},
{
topTier: { unit: 'Day', format: 'E dd yyyy', count: 1 },
bottomTier: { unit: 'Hour', format: 'hh a', count: 6 },
timelineUnitSize: 99, level: 6, timelineViewMode: 'Day', weekStartDay: 0,
updateTimescaleView: true, showTooltip: true
}
];
const onDataBound = () => {
if (ganttRef) {
ganttRef.zoomingLevels = customZoomingLevels;
}
};
return (
<GanttComponent
id="ganttDefault"
height="430px"
dataSource={data}
taskFields={taskSettings}
toolbar={toolbar}
ref={gantt => ganttRef = gantt}
dataBound={onDataBound}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="150" />
<ColumnDirective field="StartDate" headerText="Start Date" width="150" />
<ColumnDirective field="Duration" headerText="Duration" width="150" />
<ColumnDirective field="Progress" headerText="Progress" width="150" />
</ColumnsDirective>
<Inject services={[Toolbar, Selection, Filter]} />
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/32.1.19/material.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Zoom actions via methods
Zooming actions can be triggered dynamically or through external controls using the following methods:
-
Zoom In - Use zoomIn when
ZoomInexternal button was clicked, the timeline cell width is increased when the cell size exceeds the specified range and the timeline unit is changed based on the current zoom levels. -
Zoom Out - Use zoomOut when the
ZoomOutexternal button was clicked, the timeline cell width is decreased when the cell size falls behind the specified range and the timeline view mode is changed based on the current zooming levels. -
Zoom To Fit - Use fitToProject When
ZoomToFitexternal button was clicked then all the tasks are rendered within the available chart container width.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, ColumnsDirective, ColumnDirective, Inject } from '@syncfusion/ej2-react-gantt';
import { Toolbar, Selection } from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { data } from './datasource';
function App() {
let ganttRef = null;
const taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const zoomIn = () => {
if (ganttRef) ganttRef.zoomIn();
};
const zoomOut = () => {
if (ganttRef) ganttRef.zoomOut();
};
const fitToProject = () => {
if (ganttRef) ganttRef.fitToProject();
};
return (
<div>
<div style=>
<ButtonComponent id="zoomIn" onClick={zoomIn} style=>ZoomIn</ButtonComponent>
<ButtonComponent id="zoomOut" onClick={zoomOut} style=>ZoomOut</ButtonComponent>
<ButtonComponent id="fitToProject" onClick={fitToProject}>FitToProject</ButtonComponent>
</div>
<GanttComponent
id="ganttDefault"
height="430px"
dataSource={data}
taskFields={taskSettings}
ref={gantt => ganttRef = gantt}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="150" />
<ColumnDirective field="StartDate" headerText="Start Date" width="150" />
<ColumnDirective field="Duration" headerText="Duration" width="150" />
<ColumnDirective field="Progress" headerText="Progress" width="150" />
</ColumnsDirective>
<Inject services={[Toolbar, Selection]} />
</GanttComponent>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, ColumnsDirective, ColumnDirective, Inject } from '@syncfusion/ej2-react-gantt';
import { Toolbar, Selection } from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { TaskFieldsModel } from '@syncfusion/ej2-gantt';
import { data } from './datasource';
function App() {
let ganttRef: GanttComponent | null = null;
const taskSettings: TaskFieldsModel = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const zoomIn = () => {
if (ganttRef) ganttRef.zoomIn();
};
const zoomOut = () => {
if (ganttRef) ganttRef.zoomOut();
};
const fitToProject = () => {
if (ganttRef) ganttRef.fitToProject();
};
return (
<div>
<div style=>
<ButtonComponent id="zoomIn" onClick={zoomIn} style=>ZoomIn</ButtonComponent>
<ButtonComponent id="zoomOut" onClick={zoomOut} style=>ZoomOut</ButtonComponent>
<ButtonComponent id="fitToProject" onClick={fitToProject}>FitToProject</ButtonComponent>
</div>
<GanttComponent
id="ganttDefault"
height="430px"
dataSource={data}
taskFields={taskSettings}
ref={gantt => ganttRef = gantt}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="150" />
<ColumnDirective field="StartDate" headerText="Start Date" width="150" />
<ColumnDirective field="Duration" headerText="Duration" width="150" />
<ColumnDirective field="Progress" headerText="Progress" width="150" />
</ColumnsDirective>
<Inject services={[Toolbar, Selection]} />
</GanttComponent>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/32.1.19/material.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>