希沃ENOW大前端

公司官网:CVTE(广州视源股份)

团队:CVTE旗下未来教育希沃软件平台中心enow团队

「本文作者:」

前言

你盼世界,我盼望你无bug。Hello 大家好,我是霖呆呆!

哈哈哈,好久没写文章了,不过今日再次提笔就像和一位很久没见面的好朋友约了顿饭,熟悉的感觉又回来了[窃喜~]。

希沃ENOW大前端也已经发了十几篇文章,一轮了,感谢大家的支持和喜欢啦[笔芯~]。

这周给大家带来的是一篇实际开发场景不多,但却比较有意思的文章——关于如何实现一个思维导图。

唔...由于是系列的文章,所以可要做好长期作战的准备了哟,整个系列我大体是将它分为了这么几个章节:

  • 基础篇:实现思维导图的一种方案

  • 实战篇:react-topic项目初步搭建

  • 实战篇:连线的具体实现

  • 实战篇:能动的导图

根据实际情况,后面可能会写更多吧。

对于基础篇,呆呆主要是会提供一些思维导图的实现方案(非架构方面),并介绍一些svg的相关知识,为后期手撸做好准备。

思维导图:"手撸对身体不好"

呆呆:"喂,110,这里有人酒后开车"

来看看,通过阅读这篇文章你可以学习到:

  • 明确目标

  • 节点的实现思路

  • svg及二次贝塞尔曲线

  • 连线的实现思路

1. 明确目标

对于思维导图,当前市场上已经存在很多了,也不乏有一些挺不错的产品,甚至还有专业做这个的团队。

XMind:

语雀:

processon:

在要开撸之前,我们得先明确自己想要做一个什么样的产品,以及做它的意义何在,最终实现出来的产品定位是怎样的。

那么呆呆先来说说自己的想法吧。其实写这个系列的想法很简单:巩固 + 分享,因为呆呆目前的工作有一部分是与之相关的,也是自己对其的一种巩固,也许自己在写文章的时候,能产生更多好的想法用在实际工作中;另外在工作之余分享一些已有的实现方案并可以与更多的小伙伴交流;最后,如果你认为你现在的工作有点无聊了,那么跟着呆呆来手撸一个思维导图它不香吗?[偷笑~]。

至于最终要做出一个什么东西,我们看到上面例举出的思维导图,都有很多的相似点:

  • 类型丰富,左右子树布局(我们称为脑图)、组织结构图、鱼骨图等。

  • 节点都可以进行拖拽移动改变层级

  • ...

那么我们也可以来实现一个类似于上面这些的一个思维导图,最终的效果类似于下面这样:

思维导图演示.gif

产品的定型为非商业(想做到商业也很有难度啊),自己练练手,希望在这个过程中,能让你学到一些奇怪的知识

2. 节点的实现思路

2.1 方案选型

一个思维导图的实现,主要的部分无外乎两点:

  • 节点(主题)

  • 连线

对于节点的实现,方案也有很多,无论是用普通的DOM元素,还是用svg,都可以。

例如,语雀中就是使用svgpath元素:

然后进入编辑态时,开启DOM元素的contenteditable属性:

这样的实现让我想到了bpmn.js,它也是完全由svg构成:

(嘻嘻,既然说到了这,哎,推一波推一波:《全网最详bpmn教材》)

https://github.com/LinDaiDai/bpmn-chinese-document

而对于processon,好家伙,更加暴力...直接用的绝对定位:

呆呆这边也有一种推荐的实现方案:DOM元素 + flex布局。

2.2 DOM元素 + flex布局

选用DOM实现节点的原因:操作方便,API丰富,同时也易于扩展。

而对于它位置的实现,例如对于一个脑图来说,我们从整体上可以把它分为三个部分:

  • 左子树

  • 根节点

  • 右子树

这三个部分的排列,顺序上是比较固定的,那么我们就可以利用flex布局中的order属性来完成一个脑图的总体布局。

对于子树部分呢?我们也可以使用flex布局来实现,例如下图整个蓝色框的部分是右子树,绿色框部分为单个子树节点:

这样做的好处也是比较明显的,当节点的内容频繁变动的时候,不需要我们手动的去计算各个节点的位置,flex已经帮我们做好了这些事,实现动态的自适应布局。

我们可以简单的写个小demo来看看效果:

html代码:

<div class="mindMap"><div class="node rootNode">根节点</div><div class="node subTree left"><div class="treeNode">子节点</div><div class="treeNode">子节点</div><div class="treeNode">子节点</div></div><div class="node subTree right"><div class="treeNode">子节点</div><div class="treeNode">子节点</div><div class="treeNode">子节点</div></div>
</div>

css代码:

.mindMap {display: flex;align-items: center;
}
.node {width: 200px;background: rgb(192 214 255);text-align: center;color: #fff;
}
.rootNode {order: 2;background: #65bfff;height: 50px;
}
.left {order: 1;
}
.right {order: 3;
}
.subTree {display: flex;flex-direction: column;justify-content: center;
}
.treeNode {background-color: #ff6969;
}
.left .treeNode {margin-right: 56px;
}
.right .treeNode {margin-left: 56px;
}
.treeNode:not(:first-child) {margin-top: 24px;
}

最终的效果就是下面这样(丑是丑了点...咳咳凑合着看吧, 哈哈哈):

3. svg及二次贝塞尔曲线

3.1 svg简介

在继续下面的内容之前,呆呆得和大家科普一些svg的内容,它和我们后面的一些实现方案密切相关,所以我得保证你会一些最基本的知识不是。

svg为可缩放矢量图形,它使用XML格式来定义图像。我们可以像使用一个div标签一样直接在代码中使用:

<svg width="300" height="300"><line x1="0" y1="0" x2="200" y2="0" />
</svg>

而对于CSS属性,它有自己独有的三种属性:

  • fill:填充色

  • stroke:描边色

  • stroke-width:边框宽度

可以把svg标签想象成一个html标签,然后在这里面可以添加上path、line、rect等元素,来实现一个完整的矢量图。

我们常见的一些标签:

「线,line标签:」

效果:

「矩形,rect标签:」

效果:

「路径,path标签:」

效果:

「椭圆,ellipse标签:」

效果:

3.2 path元素

对于其它的一些元素呆呆这里就不展开了,可以查看《svg入门-如何手写》这篇文章。但是path元素我还是要单独说一下的,因为它是我们功能实现的"主力军"

https://juejin.cn/post/6844903589807128590

path元素可用来创建线条、曲线、弧形等等。一个path元素形状的定义是依靠于属性 d, 属性d 的值是一个 “命令 + 参数”的序列。

啥意思呢?就像下面这段代码:

<svg><path d="M10 10 L90 10"stroke="rgb(0,0,0)" stroke-width="5"></path>
</svg>

它表示的是在页面中画一个路径,然后路径遵循:

  • 移动到坐标为 (10, 10) 的点;

  • 绘制一条线到坐标为 (90, 10) 的位置。

(M: Move to 移动到某个坐标 ;    L: Line to 在某两个坐标之间画一条线)

最终的效果:

是不是很好理解呢?

3.3 二次贝塞尔曲线Q

贝塞尔曲线大家都不陌生吧,在path元素里也是有的。而且它分为两种贝塞尔曲线:

  • 三次贝塞尔曲线C

  • 二次贝塞尔曲线Q

三次贝塞尔曲线C是由一个点和两个控制点决定的,相对复杂一些,我们着重说一下二次贝塞尔曲线Q

它是path元素中用来绘制平滑曲线的一种,一条二次贝塞尔曲线的定义需要三组参数:

  • 起点坐标

  • 控制点坐标

  • 终点坐标

控制点描述的是曲线起始点的斜率,曲线上各个点的斜率,是从起点斜率到终点斜率的渐变过程。

就像上面这张图,红色的点分别表示某个点和它的控制点。

下面这段代码:

<svg><pathpath d="M10 80 Q 95 10 180 80"stroke="black" fill="transparent"></path>
</svg>

它表示的是在页面中画一个路径,然后路径遵循:

  • 移动到坐标为 (10, 80) 的点;

  • 控制点的坐标为 (95, 10);

  • 终点的坐标为 (180, 80);

  • 根据控制点得到起点和终点的斜率并在它们两之间绘制一条曲线。

最终的效果为:

4. 连线的实现思路

上面介绍了这么多svg相关的知识,不知道有没有给你实现导图中的连线提供一些思路呢?

哈哈哈,也许我们可以把整个思维导图看成是一整块svg矢量图,然后在特定的位置用path去画上线,就实现了思维导图中的枝干。

这个特定的位置也比较好理解了,因为是枝干,那么肯定是在某两个节点之间,例如根节点和它的右侧一级子节点,我们可以取根节点最右侧的中点,和一级子节点最左侧的中点。

如果对于下面这种直线枝干的话,只知道这两个点的坐标确实是可以满足的(图中的蓝色点):

但如果是对于这样的曲线路径呢?

它就可以用我们上面提到的二次贝塞尔曲线Q来实现,此时根节点上的某个坐标就可以作为曲线的起点,分支主题上的某个坐标就可以作为曲线的终点。但我们清楚,只知道起点和终点坐标还是不够的,还需要有一个控制点,才能很好的实现一个曲线。

上面的截图取的是XMind上的思维导图实现,也许不太能看出线与节点之间的关系,让我们把它的枝干移动一下,放到中心主题的最右侧:

现在,就比较直观了(假设我们再给这些点一个坐标):

  • 起点:(x1, y1)     => (100, 60)

  • 控制点:(x1, y2)  => (100, 10)

  • 终点:(x2, y2)     => (150, 10)

(这里的坐标,是以思维导图整体最左上角为坐标轴的起点)

那么实现这么一条曲线就只需要下面这行代码:

<svg><pathd="M100 60 Q 100 10 150 10"fill="transparent"stroke="rgb(102, 102, 102)"stroke-width="4"></path>
</svg>

咦~是不是感觉就有点内味了[偷笑~]。

我们就只需要再去实现一个传入两个DOM的信息,然后计算得出起点、终点、以及控制点的方法就能简单的实现连线了。

参考文章

知识无价,支持原创。

参考文章:

  • MDN-SVG

    • https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths

  • 《svg入门-如何手写》

    • https://juejin.cn/post/6844903589807128590

后语

这篇文章主要就介绍到了这里,全文看下来要手撸一个思维导图似乎很简单。那是因为我们还有很多问题没有考虑进去,例如怎么实现不同种类的思维导图,节点的框选,节点的拖拽移动等等。

就和前言中介绍的一样,这篇主要是提供一些思维导图的实现方案(非架构方面),并介绍一些svg的相关知识。后面呆呆将会构建一个项目,通过实战来和大家一起手撸它,所以请给个赞再点个关注吧,不然你可能就会错过我了哟...谢谢。

呆呆带你手撸一个思维导图-基础篇相关推荐

  1. 思维导图 基础篇(14)应用-阅读书籍

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

  2. 思维导图 基础篇(18)TBLI 考试内容 评分标准

    1 TBLI的考试内容主要分为3个部分 思维导图 艺术创作:这里会给出一个主题,比如思维大图在生活中的应用.思维导图的意义...等.之后根据主题 会指出一副标准的思维导图.时长共2小时. 思维导图 高 ...

  3. 思维导图 基础篇(11)应用-文章分析-框架法

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

  4. 思维导图 基础篇(15)应用-应对考试

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

  5. 思维导图 基础篇(05)思维方法-高度思维

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

  6. 思维导图 基础篇(01)概述

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

  7. 思维导图 基础篇(02)认知大脑

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

  8. 思维导图 基础篇(04)思维方法-水平/垂直 思考法

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出,该系列文章将分享以下内容 ...

  9. 思维导图 基础篇(12)应用-文章分析-记忆法

    系列文章解读&说明: 本系列文章主要内容是 思维导图 基础课,旨在帮助更多 热爱学习的伙伴 更具体的了解思维导图,同时也会让 更多的伙伴从 思维导图 认知 误区中走出. 系列文章总纲链接为:专 ...

最新文章

  1. 10.无重复字符的最长子串---使用滑动窗口方法和哈希表来解决
  2. Linux编程 9 (shell类型,shell父子关系,子shell用法)
  3. Linux内核ARM构架中原子变量的底层实现研究
  4. delphi读取excel
  5. linux 命令分类,常用linux 命令分类整理(篇一)
  6. 北亚利桑那大学等推出:航拍森林火情检测数据集 FLAME
  7. 深入理解 flex 布局以及计算_Flexbox, Layout
  8. 算法导论第三版第二章答案
  9. base64原理及其编解码的python实现
  10. 【大学物理·光学】圆孔的夫琅禾费衍射光学仪器的分辨本领
  11. xmapp环境搭建注意事项
  12. c语言中平方根函数(sqrt)
  13. 标注数据类型及对应的监督学习方案
  14. 阿里云盘登录空白问题解决
  15. 未来,你会反感虚拟现实沉浸式广告吗?
  16. DilatedEncoder
  17. vue PC 端使用腾讯地图定位
  18. UnityShader学习教程之<矩阵的左乘还是右乘所导致的效果问题>
  19. 【C语言详解】——文件操作(建议收藏)
  20. 微信群机器人助手多群同步群发消息,管理100个微信群!

热门文章

  1. 抽象类和抽象方法 abstract类和abstract方法
  2. 《通用数据保护条例》(GDPR)系列解读五:出海欧洲,企业必须做好四大义务
  3. winForm在多显示器(主显示器 + 扩展显示器)上显示最大化和还原操作。
  4. 足球网页设计制作 简单足球静态HTML网页作品 足球网页作业成品 学生体育运动足球网站模板
  5. 嵌入式LINUX系统程序开发
  6. webview卡顿_分享三个小技巧,微信卡顿的人千万不要错过哦
  7. 【python】如何快速生成26位字母表?这里看过来。
  8. python实现截取视频中特定帧进行保存功能
  9. 计算机软件知识产权保护主要保护哪些内容,计算机软件知识产权保护制度.pptx...
  10. 名编辑电子杂志大师教程 | 如何直接输出安卓apk格式?