【实用教程】使用思维导图增强 JavaScript甘特图项目工作流程的可见性

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求,是最完善的甘特图图表库。DHTMLX Diagram库允许用几行代码构建JavaScript流程图,通过自动布局和实时编辑器,它可以更容易地将复杂数据可视化到一个整洁的层次结构中。

在本教程中,您将学习如何将 JS 甘特图与 JS 思维导图集成并同步它们,并将向您展示 DHTMLX Gantt 与DHTMLX Diagram 库的集成案例。

DHTMLX Gantt v9.0.2最新版下载    DHTMLX Diagram v6.0.6最新版下载

在甘特图等 PM 工具中使用思维导图的好处

使用 DHTMLX 构建的甘特图可用于高效管理各种复杂的工作流程。在具有复杂任务层次结构和依赖关系的项目中,思维导图等可视化工具可以方便最终用户简化项目规划及其执行进度。借助思维导图,可以更轻松地全面了解任务的整体结构、检测潜在瓶颈并改进工作流程。

在下面的示例中,您可以看到 DHTMLX Gantt 和 Diagram 组件集成的结果。思维导图显示了甘特图中安排的项目任务。由于甘特图数据与思维导图同步,因此甘特图中引入的任何更改都将显示在思维导图中。换句话说,您可以创建、更新、删除、展开/折叠任务链,所有这些操作都将在思维导图中可视化。

需要注意的是,图表组件只允许一个根元素,而甘特图可以有多个根元素(任务)。因此,在我们的示例中,当甘特图在根级别只有一个任务时,它将是思维导图中的根元素。如果甘特图的根级别有更多任务,思维导图将补充一个附加元素,该元素将合并根级别的所有元素。

现在,我们可以按照分步说明帮助您在场景中实现类似的集成。

DHTMLX Gantt 与思维导图集成指南

  • 步骤 1:初始化图表

我们先初始化JavaScript图表组件。它应该在思维导图容器中初始化。您应该在类型参数中设置“mindmap”以获取此类型的图表。

const diagram = new dhx.Diagram ( "mindmap" , { type     : " mindmap" } ) ;
  • 步骤 2:同步数据变更

要同步更改,您需要删除当前图表数据并加载新数据。由于有多个任务,您需要将它们全部包含在数组中,然后添加事件处理程序,在其中调用负责同步更改的syncData函数。

const syncEvents = [
    "onAfterTaskAdd",
    "onAfterTaskDelete",
    "onAfterTaskUpdate",
    "onParse",
]
syncEvents.forEach(function (eventName) {
    gantt.attachEvent(eventName, function () {
        syncData();
    });
})

在syncData函数中,需要删除现有的数据。

function syncData() {
    diagram.data.removeAll();

之后,您必须以文本格式(mindData变量)保存甘特图数据。

const mindData = gantt.serialize().data;

下一步是声明syncData函数中需要的三个变量( rootItem、addRootIem、firstRootParent ) 。rootItem元素用于 Diagram 组件。 如果甘特图中有多个根任务,则此元素将添加到数据中。

const rootItem = { id: "root", text: "My project" };
let addRootItem = false;
let firstRootParent = null;

接下来,用任务遍历数组。如果检测到任务没有父任务,且firstRootParent变量中未保存任何内容,则将任务保存在此处。

mindData.forEach(function (task) {
    if (!task.parent) {
        if (!firstRootParent) {
            firstRootParent = task;
        }

如果变量不为空,则表示有多个根任务。您应该修改当前任务的父参数以及存储在firstRootParent变量中的参数。

else {
    firstRootParent.parent = "root";
    task.parent = "root";
    addRootItem = true;
}

Gantt 允许id和parent参数中的值为字符串或数字类型,但 Diagram 仅需要字符串。因此,您应该将这些参数转换为字符串类型。

task.id += "";
if (task.parent) {
    task.parent += "";
}

需要注意的是, Diagram 中的type参数设置了元素的形状。如果此参数中已经指定了某些内容,则元素将具有矩形形状。为了节省空间并使所有元素看起来更紧凑,您需要删除 type参数。

delete task.type;

之后,检查addRootItem变量的值。如果需要添加根元素,则将rootItem添加到包含数据的数组中。

if (addRootItem) {
    mindData.push(rootItem);
}
  • 步骤 3:同步两个组件的打开和关闭状态

下一步是将数据加载到图表中并运行syncOpenState函数。

diagram.data.parse(mindData);
syncOpenState();

在这个函数中,你遍历所有的甘特图任务。如果任务的层次结构是展开的,你调用Diagram 组件的expandItem()方法来展开思维导图中的分支。如果任务的层次结构是折叠的,你调用collapseItem()方法。

gantt.eachTask(function (task) {
    if (task.$open) {
        diagram.expandItem(task.id + "");
    }
    else {
        diagram.collapseItem(task.id + "");
    }
})

当甘特图中的任务展开和折叠时,您无需调用syncOpenState函数来遍历所有任务以同步更改。由于对象的 ID 相同,因此使用相同的 ID(最好将其转换为字符串)调用expandItem()和collapseItem()方法就足够了。

思维导图中的根任务在左右两侧都有子任务。因此,在扩展思维导图中的分支时,您需要知道应该从哪一侧开始。您需要为expandItem()方法指定两侧。

gantt.attachEvent("onTaskOpened", function (id) {
    diagram.expandItem(id + "", "left");
    diagram.expandItem(id + "", "right");
});

gantt.attachEvent("onTaskClosed", function (id) {
    diagram.collapseItem(id + "");
});

当思维导图中的任务展开和折叠时,您可能希望将这些变化与甘特图同步。为此,您需要添加以下代码:

diagram.events.on("afterExpand", (id, dir) => {
    gantt.silent(function () {
        const task = gantt.getTask(id)
        task.$open = true
    })
    gantt.render()
});

diagram.events.on("afterCollapse", (id, dir) => {
    gantt.silent(function () {
        const task = gantt.getTask(id)
        task.$open = false
    })
    gantt.render()
});

需要更改任务的$open属性。此属性显示任务的展开状态。最好在静默函数内执行此操作,以确保在任务展开/折叠时不会调用事件处理程序。否则,将创建一个无限循环,其中展开/折叠事件将在甘特图和思维导图中逐一调用。

最后,调用render()方法来呈现甘特图中的变化。

  • 步骤 4:甘特图初始化

完成本教程还剩一步。您需要初始化甘特图。所有初始化细节都在甘特图文档的此页面上清楚地解释。

因此,您应该获得用于管理项目工作流的工具组合,如本示例所示。

  • 结论

在管理包含多个相互关联任务的复杂项目时,思维导图等可视化工具可以很好地补充甘特图。它为项目团队提供了更全面的视角,让他们了解事情将如何展开,并根据需要做出调整。

上一篇:python爬虫js逆向进阶——请求的网页源码被加密,解密方法全过程(19)


下一篇:Qt学习笔记(四)多线程