{"id":14043,"date":"2025-06-25T09:09:32","date_gmt":"2025-06-25T06:09:32","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=14043"},"modified":"2026-09-15T15:53:51","modified_gmt":"2026-09-15T12:53:51","slug":"making-javascript-gantt-workflows-easier-to-navigate-with-a-custom-minimap","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/making-javascript-gantt-workflows-easier-to-navigate-with-a-custom-minimap\/","title":{"rendered":"Making JavaScript Gantt Workflows Easier to Navigate with a Custom Minimap"},"content":{"rendered":"<p>DHTMLX Gantt is renowned for its ability to <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/samples\/?sample=%2708_api\/10_performance_tweaks.html%27&#038;filter=%27%27\" rel=\"noopener\" target=\"_blank\">handle large projects<\/a> containing thousands of tasks without compromising performance. While large datasets are rendered smoothly, end-users may need extra time to get to specific parts of the timeline. That\u2019s where a minimap comes in handy. This small but helpful tool can enhance navigation through complex workflows. <\/p>\n<p>In this tutorial, you will learn how to add a custom minimap to a JavaScript Gantt chart using the API of our Gantt component and pure JavaScript.<\/p>\n<h5>Example of a JavaScript Gantt Chart with a Mini Map<\/h5>\n<p>Large-scale Gantt charts are notable for extensive task hierarchies and expanded timelines, where some users might get lost in the information maze. In such cases, it is nice to have a navigation tool such as a minimap. It can serve as a compact representation of the entire project (i.e., a bird-eye view of the main Gantt chart), enabling end-users to conveniently look through the whole Gantt chart. To help developers enhance the usability of the <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/\" rel=\"noopener\" target=\"_blank\">JavaScript Gantt component<\/a>, our team prepared a live sample that vividly demonstrates how a minimap can be added to real Gantt projects.<\/p>\n<p><iframe data-src=\"https:\/\/snippet.dhtmlx.com\/a4k3ilf8?mode=mobile\" frameborder=\"0\" width=\"100%\" height=\"560\"class=\"snippet-container js-iframe\"><\/iframe><a href=\"https:\/\/snippet.dhtmlx.com\/a4k3ilf8?tag=gantt&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">Check the sample ><\/a><\/p>\n<p>In this sample, you can specify any number of tasks for the project and see how convenient it becomes to interact with the Gantt chart. Using the minimap feature, you can quickly scroll through the project and instantly move to specific Gantt sections by simply clicking on them in the minimap. <\/p>\n<h5>Step-by-Step Guide on Adding a Minimap to a JS Gantt Chart<\/h5>\n<p>Generally speaking, the minimap feature is implemented by <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__multiple_gantts.html\" rel=\"noopener\" target=\"_blank\">adding a second Gantt chart<\/a> and synchronizing data between them. Now, let\u2019s delve into the details.<\/p>\n<h6>Toggling Minimap On and Off<\/h6>\n<p>To display the minimap alongside the main Gantt chart, you need to use the <strong>addMiniMap()<\/strong> function. It is called inside the <strong>toggleMinimap()<\/strong> function, which shows or hides a minimap on a web page. First, the <strong>toggleMinimap()<\/strong> function checks if the miniGantt object already exists, and if so, removes the minimap instance and its container from the DOM. If the minimap doesn\u2019t exist (i.e., it is currently hidden), the <strong>toggleMinimap()<\/strong> function calls <strong>addMiniMap()<\/strong> to generate and render the minimap.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> toggleMinimap<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">destructor<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; let oldMinimapContainer <span class=\"sy0\">=<\/span> document.<span class=\"me1\">querySelector<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;#minimap&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>oldMinimapContainer<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oldMinimapContainer.<span class=\"me1\">parentNode<\/span>.<span class=\"me1\">removeChild<\/span><span class=\"br0\">&#40;<\/span>oldMinimapContainer<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; addMiniMap<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>This toggle option allows you to show or hide the minimap with a single click, keeping the UI flexible and interactive.<\/p>\n<h6>Configuring the Minimap<\/h6>\n<p>Inside the <strong>addMiniMap()<\/strong> function, you create a new Gantt instance by calling <strong>Gantt.getGanttInstance()<\/strong>.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> addMiniMap<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; miniGantt <span class=\"sy0\">=<\/span> Gantt.<span class=\"me1\">getGanttInstance<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">show_task_cells<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">readonly<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">drag_progress<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">show_links<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">row_height<\/span> <span class=\"sy0\">=<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">min_column_width<\/span> <span class=\"sy0\">=<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">scale_height<\/span> <span class=\"sy0\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Several configuration settings should be changed to make the minimap more compact and lightweight:<\/p>\n<ul>\n<li>Hide task cells and dependencies<\/li>\n<li>Disable changing task progress<\/li>\n<li>Enable read-only mode<\/li>\n<li>Make rows and columns as small as possible<\/li>\n<li>Hide the timeline scale (by setting <strong>scale_height<\/strong> to 0)<\/li>\n<\/ul>\n<p>As a result, you get a stripped-down Gantt chart suitable for the use as a minimap.<\/p>\n<h6>Setting up Minimap Layout and Tooltips<\/h6>\n<p>Before rendering the minimap, you need to define its layout using <strong>miniGantt.config.layout<\/strong>. This configuration sets a compact structure with the timeline and scrollbars, excluding the grid panel.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">layout<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; css<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;gantt_container&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; rows<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cols<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; view<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;timeline&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scrollX<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;scrollHor&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scrollY<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;scrollVer&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; view<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;scrollbar&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;scrollVer&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; view<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;scrollbar&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;scrollHor&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>After adding the layout configuration, you can also enable the <strong>tooltip<\/strong> extension:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">plugins<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; tooltip<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>With this feature enabled, end-users will be able to view task details by hovering over a task bar in the minimap.<\/p>\n<h6>Setting Up Adaptive Time Scales<\/h6>\n<p>Now, it is time to tackle the issue of time scales in the minimap. By default, DHTMLX Gantt uses the &#8220;day&#8221; unit for the time scale, which will require too much scrolling in the minimap with large projects. The &#8220;year&#8221; scale could be an option, but it will lead to the impractical use of minimap space. Also, it is not a good fit for scenarios with not so many tasks and a small range of tasks. Therefore, the optimal approach here is to apply Zoom-to-Fit. This feature will automatically select the most appropriate scale (zoom level) in the minimap, depending on the timeline width and the number of tasks.<\/p>\n<p>All Zoom configuration settings are specified in the <strong>zoomConfig<\/strong> object:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> zoomConfig <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; levels<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;day&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;day&quot;<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;%d %M&quot;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;week&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;week&quot;<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Week #%W&quot;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;month&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;month&quot;<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;%M&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;year&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;year&quot;<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;%Y&quot;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; element<span class=\"sy0\">:<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> miniGantt.$root.<span class=\"me1\">querySelector<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;.gantt_task&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Check the full information about the Zoom extension and its configuration settings in this <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__zoom.html\" rel=\"noopener\" target=\"_blank\">section<\/a> of the Gantt documentation.<\/p>\n<h6>Implementing Zoom-to-Fit Functionality<\/h6>\n<p>You\u2019ve already configured zoom levels and loaded tasks into the minimap; now you can dynamically adjust the timeline view to fit the project\u2019s timespan. For this purpose, you can use the <strong>zoomToFit()<\/strong> function.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> zoomToFit<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> project <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">getSubtaskDates<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; areaWidth <span class=\"sy0\">=<\/span> miniGantt.$task.<span class=\"me1\">offsetWidth<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> scaleConfigs <span class=\"sy0\">=<\/span> zoomConfig.<span class=\"me1\">levels<\/span><\/div><\/div>\n<p>Here\u2019s how it goes:<\/p>\n<ul>\n<li>If the number of cells, multiplied by the minimum timeline column width, fits within the width of the minimap container, the loop breaks, and the current zoom level is selected.<\/li>\n<li>If not, the loop continues checking the next scale.<\/li>\n<\/ul>\n<p>After passing the loop, you check if the zoom level matches the length of the scale array. If yes, the previous scale is selected.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">let zoomLevel <span class=\"sy0\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">for<\/span> <span class=\"br0\">&#40;<\/span>let i <span class=\"sy0\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span> i <span class=\"sy0\">&lt;<\/span> scaleConfigs.<span class=\"me1\">length<\/span><span class=\"sy0\">;<\/span> i<span class=\"sy0\">++<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; zoomLevel <span class=\"sy0\">=<\/span> i<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> level <span class=\"sy0\">=<\/span> scaleConfigs<span class=\"br0\">&#91;<\/span>i<span class=\"br0\">&#93;<\/span>.<span class=\"me1\">scales<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> lowestScale <span class=\"sy0\">=<\/span> level<span class=\"br0\">&#91;<\/span>level.<span class=\"me1\">length<\/span> <span class=\"sy0\">-<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> columnCount <span class=\"sy0\">=<\/span> getUnitsBetween<span class=\"br0\">&#40;<\/span>project.<span class=\"me1\">start_date<\/span><span class=\"sy0\">,<\/span> project.<span class=\"me1\">end_date<\/span><span class=\"sy0\">,<\/span> lowestScale.<span class=\"me1\">unit<\/span><span class=\"sy0\">,<\/span> lowestScale.<span class=\"me1\">step<\/span> <span class=\"sy0\">||<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>columnCount <span class=\"sy0\">+<\/span> <span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">*<\/span> miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">min_column_width<\/span> <span class=\"sy0\">&lt;=<\/span> areaWidth<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>zoomLevel <span class=\"sy0\">==<\/span> scaleConfigs.<span class=\"me1\">length<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; zoomLevel<span class=\"sy0\">--;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>You pass the configuration to the <strong>applyConfig<\/strong> function, where you specify the date range and zoom level.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> applyConfig<span class=\"br0\">&#40;<\/span>config<span class=\"sy0\">,<\/span> dates<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>dates <span class=\"sy0\">&amp;&amp;<\/span> dates.<span class=\"me1\">start_date<\/span> <span class=\"sy0\">&amp;&amp;<\/span> dates.<span class=\"me1\">start_date<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">start_date<\/span> <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">date<\/span>.<span class=\"me1\">add<\/span><span class=\"br0\">&#40;<\/span>dates.<span class=\"me1\">start_date<\/span><span class=\"sy0\">,<\/span> <span class=\"sy0\">-<\/span><span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> config.<span class=\"me1\">scales<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#93;<\/span>.<span class=\"me1\">unit<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">end_date<\/span> <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">date<\/span>.<span class=\"me1\">add<\/span><span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">date<\/span><span class=\"br0\">&#91;<\/span>config.<span class=\"me1\">scales<\/span><span class=\"br0\">&#91;<\/span>config.<span class=\"me1\">scales<\/span>.<span class=\"me1\">length<\/span> <span class=\"sy0\">-<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span>.<span class=\"me1\">unit<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;_start&quot;<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#40;<\/span>dates.<span class=\"me1\">end_date<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">,<\/span> config.<span class=\"me1\">scales<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#93;<\/span>.<span class=\"me1\">unit<\/span> <span class=\"sy0\">||<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">start_date<\/span> <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">end_date<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">ext<\/span>.<span class=\"me1\">zoom<\/span>.<span class=\"me1\">setLevel<\/span><span class=\"br0\">&#40;<\/span>config.<span class=\"me1\">name<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<h6>Creating and Initializing Minimap<\/h6>\n<p>The next step is to create a new container, which will host the minimized version of the Gantt chart (i.e. minimap).<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> minimapContainer <span class=\"sy0\">=<\/span> document.<span class=\"me1\">createElement<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;div&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapContainer.<span class=\"me1\">id<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;minimap&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\ndocument.<span class=\"me1\">body<\/span>.<span class=\"me1\">appendChild<\/span><span class=\"br0\">&#40;<\/span>minimapContainer<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, you need to initialize the minimap (second Gantt) by calling the <strong>.init(&#8220;minimap&#8221;)<\/strong>, which will attach this &#8220;mini Gantt&#8221; to the container.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;minimap&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nminiGantt.$container.<span class=\"me1\">parentNode<\/span>.<span class=\"me1\">draggable<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>The second line of code is used to disable the drag-and-drop functionality, thereby preventing accidental text selection within the minimap.<\/p>\n<p>After that, you need to call the <strong>zoomToFit()<\/strong> function described in the previous section.<\/p>\n<h6>Displaying and Fitting Project Tasks in Minimap<\/h6>\n<p>To display the project workflow from the main Gantt chart in the minimap, you should serialize the project data into JSON format and then parse that data into the minimap with <strong>miniGantt.parse()<\/strong>. As a result, the data from the main Gantt chart will be duplicated in the minimap.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> ganttTasks <span class=\"sy0\">=<\/span> JSON.<span class=\"me1\">stringify<\/span><span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">serialize<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nminiGantt.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>ganttTasks<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Depending on the number of tasks and the container\u2019s height, it is necessary to adjust the height of rows with tasks and task bars.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> minimalRowSize <span class=\"sy0\">=<\/span> miniGantt.$container.<span class=\"me1\">offsetHeight<\/span> <span class=\"sy0\">\/<\/span> miniGantt.<span class=\"me1\">getTaskCount<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nminiGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">bar_height<\/span> <span class=\"sy0\">=<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">row_height<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw4\">Math<\/span>.<span class=\"me1\">max<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">Math<\/span>.<span class=\"me1\">floor<\/span><span class=\"br0\">&#40;<\/span>minimalRowSize<span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<h6>Adding a Viewport to the Minimap<\/h6>\n<p>Next, you introduce the visual drag element (<strong>minimapDrag<\/strong>), which represents the visible area (viewport) of the main Gantt chart inside the minimap. This element is appended to the minimap (<strong>miniGantt<\/strong>) container.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> minimapDrag <span class=\"sy0\">=<\/span> document.<span class=\"me1\">createElement<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;div&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">className<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;minimap_drag&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">draggable<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">left<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;0px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">width<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw4\">Math<\/span>.<span class=\"me1\">max<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>gantt.$task.<span class=\"me1\">offsetWidth<\/span> <span class=\"sy0\">\/<\/span> gantt.$task.<span class=\"me1\">scrollWidth<\/span> <span class=\"sy0\">*<\/span> miniGantt.$task.<span class=\"me1\">offsetWidth<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">20<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">top<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;0px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">height<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw4\">Math<\/span>.<span class=\"me1\">max<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>gantt.$task.<span class=\"me1\">offsetHeight<\/span> <span class=\"sy0\">\/<\/span> gantt.$task_bg.<span class=\"me1\">scrollHeight<\/span> <span class=\"sy0\">*<\/span> miniGantt.$task.<span class=\"me1\">offsetHeight<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">20<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\nminiGantt.$container.<span class=\"me1\">appendChild<\/span><span class=\"br0\">&#40;<\/span>minimapDrag<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>The drag element size is calculated based on how much of the full Gantt chart is currently visible. A minimum size is set to ensure the drag element stays large enough to easily click and move, even for big projects.<\/p>\n<h6>Making the Minimap Interactive<\/h6>\n<p>Now that the minimap is fully rendered, you come to the point of implementing interactivity within the minimap by setting up the logic for drag (scroll) behavior. It will take several steps:<\/p>\n<p><strong><\/p>\n<ol>\n<li>Adding the mousedown event<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>Using the <strong>mousedown<\/strong> event listener, you determine which element is being clicked on. If it is the minimap (mini Gantt) container, the initial scroll position is stored. If it is the drag handle, you disable all drag handle events for the minimap and enable the <strong>dragActualGantt<\/strong> variable.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">dragMiniGantt<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\nminiGantt.<span class=\"me1\">dragActualGantt<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\nlet initialDragPosition <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\nlet initialScroll <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">getScrollState<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\nwindow.<span class=\"me1\">addEventListener<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'mousedown'<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">dragMiniGantt<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> minimapElement <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">closest<\/span><span class=\"br0\">&#40;<\/span>e.<span class=\"me1\">target<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;.minimap_drag&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>dragInsideContainer<span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> miniGantt.$container<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; initialScroll <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">getScrollState<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>minimapElement <span class=\"sy0\">&amp;&amp;<\/span> dragInsideContainer<span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> minimapElement<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">dragActualGantt<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; minimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">pointerEvents<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;none&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p><strong><\/p>\n<ol start=\"2\">\n<li>Adding the mouseup event<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>With the <strong>mouseup<\/strong> event listener, you reset all the variables, disable the ability to drag tasks, and return mouse events to the drag handle.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">window.<span class=\"me1\">addEventListener<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'mouseup'<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">dragMiniGantt<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">dragActualGantt<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; initialDragPosition <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; minimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">pointerEvents<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;all&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p><strong><\/p>\n<ol start=\"3\">\n<li>Adding the onMouseMove event<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>The <strong>onMouseMove<\/strong> listener is responsible for the actual dragging (scrolling) operation. It is added not to the window object, but to the minimap (<strong>miniGantt<\/strong> object).<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onMouseMove&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><\/div><\/div>\n<p><strong><\/p>\n<ol start=\"4\">\n<li>Setting the minimap\u2019s drag handle position<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>If the <strong>dragActualGantt<\/strong> variable is enabled, you check the mouse position relative to the mini Gantt (minimap) timeline and retrieve the coordinates. After that, you subtract half of the mini drag\u2019s width and height from these coordinates to place the drag handle centered on the mouse position.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dragActualGantt<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> position <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">getRelativeEventPosition<\/span><span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> miniGantt.$task_data<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> taskRow <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">closest<\/span><span class=\"br0\">&#40;<\/span>e.<span class=\"me1\">target<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;[data-task-id]&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>taskRow<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> relativePosition <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">getRelativeEventPosition<\/span><span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> miniGantt.$container<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">dragPositionX<\/span> <span class=\"sy0\">=<\/span> relativePosition.<span class=\"me1\">x<\/span> <span class=\"sy0\">-<\/span> minimapDrag.<span class=\"me1\">offsetWidth<\/span> <span class=\"sy0\">\/<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">dragPositionY<\/span> <span class=\"sy0\">=<\/span> relativePosition.<span class=\"me1\">y<\/span> <span class=\"sy0\">-<\/span> minimapDrag.<span class=\"me1\">offsetHeight<\/span> <span class=\"sy0\">\/<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>For the X coordinate, you convert the mouse position in the mini-Gantt into a date, then calculate the corresponding horizontal position for this date in the main Gantt. For the Y coordinate, you get the vertical position of the corresponding task in the main Gantt.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> id <span class=\"sy0\">=<\/span> taskRow.<span class=\"me1\">dataset<\/span>.<span class=\"me1\">taskId<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> x <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">posFromDate<\/span><span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dateFromPos<\/span><span class=\"br0\">&#40;<\/span>position.<span class=\"me1\">x<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">-<\/span> gantt.$task.<span class=\"me1\">offsetWidth<\/span> <span class=\"sy0\">\/<\/span> <span class=\"nu0\">3<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> y <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTaskPosition<\/span><span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">top<\/span> <span class=\"sy0\">-<\/span> gantt.$task.<span class=\"me1\">offsetHeight<\/span> <span class=\"sy0\">\/<\/span> <span class=\"nu0\">3<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, the drag\u2019s position in the minimap (miniGantt) is updated to follow the drag position, and both the minimap and the main Gantt charts are scrolled to the calculated coordinates.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">minimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">left<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dragPositionX<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\nminimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">top<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dragPositionY<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\ngantt.<span class=\"me1\">scrollTo<\/span><span class=\"br0\">&#40;<\/span>x<span class=\"sy0\">,<\/span> y<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p><strong><\/p>\n<ol start=\"5\">\n<li>Auto-scrolling the minimap while dragging<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>Using the <strong>scrollMiniGantt<\/strong>() function, you check whether the current drag position has reached or crossed the minimap borders (based on the predefined offset threshold). If so, you scroll the minimap using the <strong>scrollTo()<\/strong> method. After a timeout, the function is called again to check whether further scrolling is needed.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">scrollMiniGantt<span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dragPositionX<\/span><span class=\"sy0\">,<\/span> miniGantt.<span class=\"me1\">dragPositionY<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">function<\/span> scrollMiniGantt<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> newScrollPosition <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">getScrollState<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> leftBorder <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">dragPositionX<\/span> <span class=\"sy0\">-<\/span> scrollOffset <span class=\"sy0\">\/<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> rightBorder <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">dragPositionX<\/span> <span class=\"sy0\">-<\/span> <span class=\"br0\">&#40;<\/span>miniGantt.$task.<span class=\"me1\">offsetWidth<\/span> <span class=\"sy0\">-<\/span> scrollOffset<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> topBorder <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">dragPositionY<\/span> <span class=\"sy0\">-<\/span> scrollOffset <span class=\"sy0\">\/<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> bottomBorder <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">dragPositionY<\/span> <span class=\"sy0\">-<\/span> <span class=\"br0\">&#40;<\/span>miniGantt.$task_data.<span class=\"me1\">offsetHeight<\/span> <span class=\"sy0\">-<\/span> scrollOffset<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; let shouldScroll <span class=\"sy0\">=<\/span> <span class=\"kw2\">false<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>leftBorder <span class=\"sy0\">&lt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newScrollPosition.<span class=\"me1\">x<\/span> <span class=\"sy0\">-=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollWidth<\/span> <span class=\"sy0\">\/<\/span> scrollOffset<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; shouldScroll <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>rightBorder <span class=\"sy0\">&gt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newScrollPosition.<span class=\"me1\">x<\/span> <span class=\"sy0\">+=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollWidth<\/span> <span class=\"sy0\">\/<\/span> scrollOffset<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; shouldScroll <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>topBorder <span class=\"sy0\">&lt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newScrollPosition.<span class=\"me1\">y<\/span> <span class=\"sy0\">-=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollHeight<\/span> <span class=\"sy0\">\/<\/span> scrollOffset<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; shouldScroll <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>bottomBorder <span class=\"sy0\">&gt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; shouldScroll <span class=\"sy0\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newScrollPosition.<span class=\"me1\">y<\/span> <span class=\"sy0\">+=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollHeight<\/span> <span class=\"sy0\">\/<\/span> scrollOffset<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>shouldScroll<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">scrollTo<\/span><span class=\"br0\">&#40;<\/span>newScrollPosition.<span class=\"me1\">x<\/span><span class=\"sy0\">,<\/span> newScrollPosition.<span class=\"me1\">y<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; setTimeout<span class=\"br0\">&#40;<\/span><span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scrollMiniGantt<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">4<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p><strong><\/p>\n<ol start=\"6\">\n<li>Dragging the minimap itself<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>If the <strong>dragMiniGantt<\/strong> variable is enabled, it means the minimap itself is being dragged, not the drag handle. In this case, you check whether the drag handle is still inside the minimap container using the <strong>dragInsideContainer<\/strong> function.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">else<\/span> <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dragMiniGantt<\/span> <span class=\"sy0\">&amp;&amp;<\/span> dragInsideContainer<span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> miniGantt.$container<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><\/div><\/div>\n<p>Then, you determine the initial drag position and calculate the dragged distance (expressed as a percentage) relative to the width and height of the minimap container.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> dragPos <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">getRelativeEventPosition<\/span><span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> miniGantt.$container<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\ninitialDragPosition <span class=\"sy0\">=<\/span> initialDragPosition <span class=\"sy0\">||<\/span> dragPos<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> percentX <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>initialDragPosition.<span class=\"me1\">x<\/span> <span class=\"sy0\">-<\/span> dragPos.<span class=\"me1\">x<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">\/<\/span> miniGantt.$container.<span class=\"me1\">scrollWidth<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> percentY <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>initialDragPosition.<span class=\"me1\">y<\/span> <span class=\"sy0\">-<\/span> dragPos.<span class=\"me1\">y<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">\/<\/span> miniGantt.$container.<span class=\"me1\">scrollHeight<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> positionPercentX <span class=\"sy0\">=<\/span> percentX <span class=\"sy0\">*<\/span> miniGantt.$task_bg.<span class=\"me1\">scrollWidth<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> positionPercentY <span class=\"sy0\">=<\/span> percentY <span class=\"sy0\">*<\/span> miniGantt.$task_bg.<span class=\"me1\">scrollHeight<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, you add the percentage values \u200b\u200bto the initial scroll position and scroll the minimap using the <strong>scrollTo()<\/strong> method.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> newPositionX <span class=\"sy0\">=<\/span> initialScroll.<span class=\"me1\">x<\/span> <span class=\"sy0\">+<\/span> positionPercentX<br \/>\n<span class=\"kw1\">const<\/span> newPositionY <span class=\"sy0\">=<\/span> initialScroll.<span class=\"me1\">y<\/span> <span class=\"sy0\">+<\/span> positionPercentY<br \/>\n<br \/>\nminiGantt.<span class=\"me1\">scrollTo<\/span><span class=\"br0\">&#40;<\/span>newPositionX<span class=\"sy0\">,<\/span> newPositionY<span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>It might seem that the <strong>drag_timeline<\/strong> extension would help do the same job. It would work, but not the way you need. The scrolling would be calculated by coordinates (not by percentage values), i.e. in very small steps.<\/p>\n<p><strong><\/p>\n<ol start=\"7\">\n<li>Adding click events<\/li>\n<\/ol>\n<p><\/strong><\/p>\n<p>Also, you need to add a couple of click events for interacting with the minimap. First is the <strong>onEmptyClick<\/strong> event, which will fire after a click on an empty space in the Gantt chart (not on tasks) in the minimap. The main Gantt chart will scroll to the same coordinates. You get these coordinates in the same way as for the case described above, when you dragged the minimap drag handle.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onEmptyClick&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> position <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">getRelativeEventPosition<\/span><span class=\"br0\">&#40;<\/span>e<span class=\"sy0\">,<\/span> miniGantt.$task_data<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> taskRow <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">closest<\/span><span class=\"br0\">&#40;<\/span>e.<span class=\"me1\">target<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;[data-task-id]&quot;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>taskRow<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> id <span class=\"sy0\">=<\/span> taskRow.<span class=\"me1\">dataset<\/span>.<span class=\"me1\">taskId<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> y <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getTaskPosition<\/span><span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">getTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">top<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> x <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">posFromDate<\/span><span class=\"br0\">&#40;<\/span>miniGantt.<span class=\"me1\">dateFromPos<\/span><span class=\"br0\">&#40;<\/span>position.<span class=\"me1\">x<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">scrollTo<\/span><span class=\"br0\">&#40;<\/span>x<span class=\"sy0\">,<\/span> y<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>In addition, you need to add the <strong>onTaskClick<\/strong> event for the minimap. When a task is clicked in the minimap, the corresponding task is brought into view in the main Gantt chart using the <strong>showTask()<\/strong> method.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onTaskClick&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">showTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>That\u2019s it. Now, your minimap fully supports dragging, smooth scrolling, and click-based navigation.<\/p>\n<h6>Synchronizing the Main Gantt Chart and Minimap<\/h6>\n<p>The next major step is to synchronize the minimap and the main Gantt chart so that both views stay aligned and always show the same part of the project.<\/p>\n<p>To do that, you need to add several event listeners, such as <strong>onAfterTaskAdd<\/strong>, <strong>onAfterTaskDelete<\/strong>, and <strong>onAfterTaskUpdate<\/strong>.  Using these listeners, you will trigger corresponding actions in the minimap whenever tasks are added, deleted, or updated in the main Gantt chart.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onAfterTaskAdd&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> task<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">addTask<\/span><span class=\"br0\">&#40;<\/span>task<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\ngantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onAfterTaskDelete&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> task<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">deleteTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\ngantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onAfterTaskUpdate&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> task<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; miniGantt.<span class=\"me1\">updateTask<\/span><span class=\"br0\">&#40;<\/span>id<span class=\"sy0\">,<\/span> task<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>After that, you add the <strong>onGanttScroll<\/strong> listener, which updates the minimap\u2019s scroll position whenever the main Gantt is scrolled.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">gantt.<span class=\"me1\">attachEvent<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onGanttScroll&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span>left<span class=\"sy0\">,<\/span> top<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>miniGantt <span class=\"sy0\">&amp;&amp;<\/span> <span class=\"sy0\">!<\/span>miniGantt.<span class=\"me1\">dragActualGantt<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><\/div><\/div>\n<p>To obtain the scroll coordinates from the main Gantt, you first take the full width and height of its timeline, and calculate how far the current scroll position is as a percentage of these dimensions. Then, you calculate two coordinate points in the minimap that represent the currently visible area in the main Gantt chart:<\/p>\n<ul>\n<li>(x1, y1) &#8211; the top-left point of the visible area<\/li>\n<li>(x2, y2) &#8211; the bottom-right point of the visible area<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">const<\/span> scroll <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">getScrollState<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> fullWidth <span class=\"sy0\">=<\/span> gantt.$task_data.<span class=\"me1\">scrollWidth<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> fullHeight <span class=\"sy0\">=<\/span> gantt.$task_data.<span class=\"me1\">scrollHeight<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> scrollX1Percent <span class=\"sy0\">=<\/span> scroll.<span class=\"me1\">x<\/span> <span class=\"sy0\">\/<\/span> fullWidth<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> scrollY1Percent <span class=\"sy0\">=<\/span> scroll.<span class=\"me1\">y<\/span> <span class=\"sy0\">\/<\/span> fullHeight<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> x1 <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">posFromDate<\/span><span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">dateFromPos<\/span><span class=\"br0\">&#40;<\/span>scroll.<span class=\"me1\">x<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> y1 <span class=\"sy0\">=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollHeight<\/span> <span class=\"sy0\">*<\/span> scrollY1Percent<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> scrollX2Percent <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>scroll.<span class=\"me1\">x<\/span> <span class=\"sy0\">+<\/span> gantt.$task.<span class=\"me1\">offsetWidth<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">\/<\/span> fullWidth<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> scrollY2Percent <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>scroll.<span class=\"me1\">y<\/span> <span class=\"sy0\">+<\/span> gantt.$task.<span class=\"me1\">offsetHeight<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">\/<\/span> fullHeight<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> x2 <span class=\"sy0\">=<\/span> miniGantt.<span class=\"me1\">posFromDate<\/span><span class=\"br0\">&#40;<\/span>gantt.<span class=\"me1\">dateFromPos<\/span><span class=\"br0\">&#40;<\/span>scroll.<span class=\"me1\">x<\/span> <span class=\"sy0\">+<\/span> gantt.$task.<span class=\"me1\">offsetWidth<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> y2 <span class=\"sy0\">=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollHeight<\/span> <span class=\"sy0\">*<\/span> scrollY2Percent<span class=\"sy0\">;<\/span><\/div><\/div>\n<p>The next step is to get the current scroll position of the minimap timeline and calculate the visible area boundaries. Then, you check if the Gantt\u2019s visible area (represented by x1 and y1) is inside this minimap viewport. If it\u2019s not, you scroll the minimap to bring it into view.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">miniGantt.<span class=\"me1\">utils<\/span>.<span class=\"me1\">dom<\/span>.<span class=\"me1\">getNodePosition<\/span><span class=\"br0\">&#40;<\/span>miniGantt.$task_data<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> miniGanttLeft <span class=\"sy0\">=<\/span> miniGantt.$task.<span class=\"me1\">scrollLeft<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> miniGanttRight <span class=\"sy0\">=<\/span> miniGantt.$task.<span class=\"me1\">scrollLeft<\/span> <span class=\"sy0\">+<\/span> miniGantt.$task.<span class=\"me1\">offsetWidth<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> miniGanttTop <span class=\"sy0\">=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollTop<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> miniGanttBottom <span class=\"sy0\">=<\/span> miniGantt.$task_data.<span class=\"me1\">scrollTop<\/span> <span class=\"sy0\">+<\/span> miniGantt.$task.<span class=\"me1\">offsetHeight<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> xInsideViewport <span class=\"sy0\">=<\/span> miniGanttLeft <span class=\"sy0\">&lt;=<\/span> x1 <span class=\"sy0\">&amp;&amp;<\/span> x1 <span class=\"sy0\">&lt;=<\/span> miniGanttRight<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> yInsideViewport <span class=\"sy0\">=<\/span> miniGanttTop <span class=\"sy0\">&lt;=<\/span> y1 <span class=\"sy0\">&amp;&amp;<\/span> y1 <span class=\"sy0\">&lt;=<\/span> miniGanttBottom<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>xInsideViewport <span class=\"sy0\">||<\/span> <span class=\"sy0\">!<\/span>yInsideViewport<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; miniGantt.<span class=\"me1\">scrollTo<\/span><span class=\"br0\">&#40;<\/span>x1<span class=\"sy0\">,<\/span> y1<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>It remains only to repeat a similar check for the minimap drag handle to ensure it stays correctly aligned with the visible area of the main Gantt chart.<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">let minimapDrag <span class=\"sy0\">=<\/span> miniGantt.$container.<span class=\"me1\">querySelector<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;.minimap_drag&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> miniMapDragLeft <span class=\"sy0\">=<\/span> minimapDrag.<span class=\"me1\">offsetLeft<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> miniMapDragRight <span class=\"sy0\">=<\/span> minimapDrag.<span class=\"me1\">offsetLeft<\/span> <span class=\"sy0\">+<\/span> minimapDrag.<span class=\"me1\">offsetWidth<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> miniMapDragTop <span class=\"sy0\">=<\/span> minimapDrag.<span class=\"me1\">offsetTop<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> miniMapDragBottom <span class=\"sy0\">=<\/span> minimapDrag.<span class=\"me1\">offsetTop<\/span> <span class=\"sy0\">+<\/span> minimapDrag.<span class=\"me1\">offsetHeight<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> x1InsideDrag <span class=\"sy0\">=<\/span> miniMapDragLeft <span class=\"sy0\">&lt;=<\/span> x1 <span class=\"sy0\">&amp;&amp;<\/span> x1 <span class=\"sy0\">&lt;=<\/span> miniMapDragRight<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> y1InsideDrag <span class=\"sy0\">=<\/span> miniMapDragTop <span class=\"sy0\">&lt;=<\/span> y1 <span class=\"sy0\">&amp;&amp;<\/span> y1 <span class=\"sy0\">&lt;=<\/span> miniMapDragBottom<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> x2InsideDrag <span class=\"sy0\">=<\/span> miniMapDragLeft <span class=\"sy0\">&lt;=<\/span> x2 <span class=\"sy0\">&amp;&amp;<\/span> x2 <span class=\"sy0\">&lt;=<\/span> miniMapDragRight<span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw1\">const<\/span> y2InsideDrag <span class=\"sy0\">=<\/span> miniMapDragTop <span class=\"sy0\">&lt;=<\/span> y2 <span class=\"sy0\">&amp;&amp;<\/span> y2 <span class=\"sy0\">&lt;=<\/span> miniMapDragBottom<span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>x1InsideDrag <span class=\"sy0\">||<\/span> <span class=\"sy0\">!<\/span>y1InsideDrag <span class=\"sy0\">||<\/span> <span class=\"sy0\">!<\/span>x2InsideDrag <span class=\"sy0\">||<\/span> <span class=\"sy0\">!<\/span>y2InsideDrag<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; minimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">left<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>x1 <span class=\"sy0\">-<\/span> miniGantt.$task_data.<span class=\"me1\">scrollWidth<\/span> <span class=\"sy0\">\/<\/span> scrollOffset <span class=\"sy0\">-<\/span> miniGantt.$task.<span class=\"me1\">scrollLeft<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; minimapDrag.<span class=\"me1\">style<\/span>.<span class=\"me1\">top<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>y1 <span class=\"sy0\">-<\/span> miniGantt.$task_data.<span class=\"me1\">scrollTop<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">+<\/span> <span class=\"st0\">&quot;px&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<h6>Final Touch<\/h6>\n<p>The last thing to do is to add styles for the minimap and the drag handle, as well as the minimum width for the task bars:<\/p>\n<div class=\"codecolorer-container css default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"css codecolorer\">.gantt_bar_task<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">min-width<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">1px<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"re0\">#minimap<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">position<\/span><span class=\"sy0\">:<\/span> <span class=\"kw2\">fixed<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">bottom<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">15px<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">right<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">15px<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">width<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">200px<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">height<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">200px<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">opacity<\/span><span class=\"sy0\">:<\/span> <span class=\"nu0\">0.7<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">z-index<\/span><span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"re0\">#minimap<\/span> .gantt_row<span class=\"sy0\">,<\/span><br \/>\n<span class=\"re0\">#minimap<\/span> <span class=\"re1\">.gantt_task_row<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">border-bottom<\/span><span class=\"sy0\">:<\/span> <span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"re0\">#minimap<\/span> <span class=\"re1\">.minimap_drag<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">background<\/span><span class=\"sy0\">:<\/span> <span class=\"kw4\">cornflowerblue<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">opacity<\/span><span class=\"sy0\">:<\/span> <span class=\"nu0\">0.5<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">width<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">20px<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">height<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">20px<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">position<\/span><span class=\"sy0\">:<\/span> <span class=\"kw2\">absolute<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">top<\/span><span class=\"sy0\">:<\/span> <span class=\"re3\">0px<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>By following the steps above, you can successfully add a fully functional minimap to your Gantt chart like in this DHTMLX <a href=\"https:\/\/snippet.dhtmlx.com\/a4k3ilf8?tag=gantt&#038;mode=wide\" rel=\"noopener\" target=\"_blank\">sample<\/a>.<\/p>\n<h5>Wrapping Up<\/h5>\n<p>In this tutorial, we covered how to create the minimap, synchronize it with the main JavaScript Gantt chart, and handle user interactions, such as dragging, clicking, and scrolling. The minimap enables end-users to quickly navigate through large projects, improving usability and user experience. This approach can be further customized depending on your project needs using the extensive Gantt API. Having doubts? Just download a <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/download.shtml\" rel=\"noopener\" target=\"_blank\">free 30-day trial version<\/a> of our Gantt component and give it a test run.<\/p>\n<h5>Related Materials<\/h5>\n<ul>\n<li><a href=\"https:\/\/dhtmlx.com\/blog\/tutorials\/?tag=gantt\" rel=\"noopener\" target=\"_blank\">DHTMLX Gantt tutorials<\/a><\/li>\n<li><a href=\"https:\/\/docs.dhtmlx.com\/gantt\/\" rel=\"noopener\" target=\"_blank\">DHTMLX Gantt documentation<\/a><\/li>\n<li><a href=\"https:\/\/docs.dhtmlx.com\/gantt\/demos\/\" rel=\"noopener\" target=\"_blank\">DHTMLX Gantt samples<\/a><\/li>\n<li><a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/download.shtml\" rel=\"noopener\" target=\"_blank\">DHTMLX Gantt trial version<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>DHTMLX Gantt is renowned for its ability to handle large projects containing thousands of tasks without compromising performance. While large datasets are rendered smoothly, end-users may need extra time &#8230;<\/p>\n","protected":false},"author":101014,"featured_media":14051,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71],"tags":[33,20],"class_list":["post-14043","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-all-posts","tag-gantt"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14043","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/101014"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=14043"}],"version-history":[{"count":28,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14043\/revisions"}],"predecessor-version":[{"id":15903,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14043\/revisions\/15903"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/14051"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=14043"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=14043"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=14043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}