思维导图混合布局实现

1,105 阅读3分钟

前言

原计划中,计划一篇文章写完思维导图布局相关的所有内容,写到一半发现, 可能内容过于冗长,对于阅读的小伙伴来说并不好理解,遂拆分为两篇文章。

可以先阅读此篇, 作为前提 -> 包含概要的思维导图布局实现

xmind 混合布局说明

不包含概要的混合布局

如图所示, 一个仅包含普通节点的混合布局,让我们看一下, 在这个布局中, 其实所有节点的大小叠加方式,都是通过父子节点层层递归叠加计算而来。

image.png

在浏览器的默认布局中,当未设置父节点大小的情况下,子节点会撑开父节点,子节点之间会按照一定规则排列,父节点会根据排列得到子节点的大小总和, 最终得到大小之和。

image.png

对于不同类型的思维导图布局,无论是 tree (树形图), 组织架构图,思维导图,或者其他等。。

image.png

从这里不同类型的图的布局其实可以抽象出几条规则:

  • 任意节点都是一个最小子树 (可以仅包含一个节点)
  • 计算任意子树(任意节点)大小的时候,无需关心子节点内的布局实现
  • 不同类型的布局可以自定义子树大小的计算方式

那么问题基本已经解决了,让我们来看一下如何抽象实现

混合布局的实现

根据上文分析,我们先定义如下属性,也就是任何一种布局只要符合提供节点和子树的大小,无需关心 layoutTree 是如何计算出来的,那么一个思维导图的混合布局, 本身就已经天然支持了。

interface BaseNode {
  /**
   * node width
   * 节点的宽高
  */
  contentWidth: number;
  /**
   * node height 
   * 节点的高度
  */
  contentHeight: number;
  /**
   * subTree width 
   * 子树的宽度
  */
  layoutWidth: number;
    /**
   * subTree height 
   * 子树的高度
  */
  layoutHeight: number;
}

带有概要的布局实现

本篇讲述的是混合布局,所以不会讲解概要的实现,在上一篇文章中,本身对于概要的实现 包含概要的思维导图布局实现 已经讲解的非常清楚明了,概要应该如何计算和实现。

那么当在混合布局之中计算概要实现方式,依然同理, 提供统一的定义和不同布局之间概要的混合计算方式,那么问题就可以得到解决。

image.png

分析如下:

  • 同一子节点下的概要会可以重叠
  • 同一子节点下的直接子节点布局方式相同
  • 不同层级的概要,布局上计算方式为相互叠加 (看上篇分析)
  • 概要会影响父节点之间的间距

那么本身基于这些信息,定义出一个对应的包含概要的大小布局说明,那么问题其实也可以得到解决。

总结

混合布局的难点在于认识到混合布局的抽象接口是什么,基于此抽象接口,各自实现自定义布局。那么整体实现就会变得相当清晰。

image.png