我开源了一个思维导图

在线地址:https://wanglin2.github.io/mind-map/#/index

仓库地址:https://github.com/wanglin2/mind-map

起源

我对思维导图最初的了解来源于我的老婆,她很喜欢用思维导图来记录各种东西,看的多了,作为一个前端,就会好奇这东西是怎么实现的,于是我在网上搜了一下,看到了一篇介绍思维导图基本结构–逻辑结构图的一种布局算法,然后我就想,布局算法有了,我再实现一下节点内容渲染、节点连线、展开收起、编辑之类的功能不就可以实现一个简单的思维导图了么,顺便还可以产出一篇文章,是的,能写文章是我做这个的最大动力。

于是没有经过太多思考就开始做,毕竟最初也只是打算做一个文章的配套 demo ,这当然也给后面带来了很多问题。

基本设计是核心库使用纯 js 实现,这样能跨框架使用;一个主类 + 若干个功能类,通过事件机制,方便扩展;不做UI界面的事情,只做逻辑,提供相关 api 给使用方调用,然后 dem o界面使用 Vue2+ElementUI 实现。

做的过程中主要的难点是几种布局结构的实现,布局其实就是计算所有节点在画布上的位置,除了逻辑结构图的思路是参考网络上的那篇文章外,另外还实现了思维导图、组织结构图、目录组织图,需要不断思考,找规律,尝试,费了我不少脑细胞。

于是没多久,就做完了并且写了这篇文章Web思维导图实现的技术点分析,然后,反响非常一般,于是文末计划的第二篇也没有再写,这个 demo 大概率也会和其他 demo 一样躺在 github 里不会再更新。

目前为止,作为一个思维导图的 demo ,其实可以用,但是存在两个大问题:

1.性能很差,节点数量多了操作很卡;

2.功能很简陋、bug 很多;

结局就是我老婆都嫌弃,继续用她的 Xmind 。

过程

功能

做完后,因为发到了 npm ,并且文档写的还算比较详细,所以时不时会收到一些 star ,但是继续维护是当收到 issue 开始的,收到第一个 issue 还是很激动的,毕竟这代表真的有人在用,虽然我自己都觉得这个东西很草率。

后续就是有人提了 bug ,我就改 bug ,有人提了需求,合理的话,我就加功能,渐渐地,issue 越来越多,有来自国内的,也有来自国外的,于是功能慢慢完整,bug 也逐渐减少。概要、节点拖拽、小地图、水印、关联线、多种节点形状、多种连线类型、导入导出支持 markdown ,xmind、键盘导航、节点富文本编辑、支持触摸事件、支持更多结构等等,你能想到的一个思维导图的功能基本都具备了。

前面提到做之前并没有进行太多思考和设计,于是在功能膨胀的时候,维护就会很痛苦,会感觉代码很乱,内部方法内部变量没有和暴露出去的变量方法做区分,有些类的代码量过于庞大,有些逻辑过于混乱,不够清晰,有些地方实现不合理,总之,问题很多,但是又不愿重构。

其中有一些比较好的建议,比如希望能按需引入一些功能,因为有些场景可能只做一个展示的功能,并不需要各种操作的逻辑,那么引入完整的代码其实没有必要,于是我果断改成了插件化的架构,得益于一个功能一个类和事件机制,改成插件非常简单,不要在主类默认引入所有类,改成按需引入进行实例化就行了,后续新增的非核心功能都可以做成插件,其他开发者也可以开发插件,虽然目前还没有。

又比如支持节点富文本编辑和自定义节点内容,因为实现是基于 svg 的,最初只能给整个节点的所有文本一起应用文本样式,不能针对部分文本,考虑到这也是一个比较实用的功能,于是就尝试用 svg 的 foreignObject 标签嵌入 html 实现富文本展示,使用Quill编辑器实现编辑,这个功能做完后,又想到反正节点中都部分嵌入了 html 了,不如再开放一下,允许整个节点完全使用用户自定义的 html 内容,这个做完后,其实可以大大扩展使用场景,就我自己而言,公司项目里做组织架构图基本上可以百分之九十还原设计稿。

性能

因为众多的 issue ,功能和 bug 的问题已经解决的差不多了,但是还有一个很重要的问题,就是性能。

性能为什么差,原因很简单,因为最初我的做法是把 svg 当 canvas 用,数据驱动视图,数据改变了,就删除所有节点,然后重新创建,这样实现是非常简单,但是根本没法用,毕竟就算用 canvas 你也得做点优化,结果就是几十个节点已经卡的不行了,作为一个 demo 都无法接受,于是我当时做了一定的优化,节选一下我前面提到的文章里的内容:

所以笔者最后采用的方法的是不再每次都完全重新渲染,而是按需进行渲染,比如点击节点激活该节点的时候,不需要重新渲染其他节点,只需要重新渲染被点击的节点就可以了,又比如某个节点收缩或展开时,其他节点只是位置需要变化,节点内容并不需要重新渲染,所以只需要重新计算其他节点的位置并把它们移动过去即可,这样额外的好处是还可以让它们通过动画的方式移动过去,其他相关的操作也是如此,尽量只更新必要的节点和进行必要的操作,改造完后虽然还是会存在一定卡顿的现象,但是相比之前已经好了很多。

进行了这些优化以后,只能说有点用处,但不多,其他很多操作还是需要全量渲染,尤其是常用的前进后退,意味着前进或回退一次,整个思维导图都会清空再重新创建,非常慢,体验很差,于是在用户提了几次这个问题后,我就决定要解决这个问题。

很多问题都是当时想不到,后面就会突然来灵感,也可能是看多了 Vue 虚拟 dom 的 diff 算法,想到 Vue 可以通过 key 来复用节点,那么我是不是也可以根据 id 来复用,于是我创建了一个节点缓存池,将所有创建过的节点实例都缓存起来,然后每次渲染时通过数据唯一的 id 来检查是否存在可复用节点,如果没有,那就代表是新增的节点,创建新节点并添加到缓存;如果有,那么就判断节点数据是否发生了改变,没有改变直接复用,发生了改变那么判断是否可以进行更新,如果更新成本高也是重新创建;另外会创建一个本次渲染的缓存和上一次的缓存,用于找出被删除的节点;当然,为了避免缓存节点数量无限膨胀,也通过 lru 缓存算法来管理。

除了这个大优化,我还仔细阅读和梳理了渲染部分的代码逻辑,然后做了一些小优化,比如改成异步渲染节点,让页面可以在节点渲染时响应其他操作,而不是完全卡死;又比如将渲染任务放到队列中,在下一个事件循环里进行处理,合并掉一些中间状态;又比如避免没有必要的函数调用,因为一些看着没有影响的函数调用也会耗费时间,等等,通过这一系列的优化,卡顿问题有了很大的改善,但毕竟每个节点仍是 dom 元素,所以当节点数量达到一定量级的时候还是会存在问题,但是一个思维导图几千个节点的场景我觉得毕竟是少数,其实已经可以满足绝大部分使用场景,至少后面基本没有用户提到性能的问题。

文档

最开始文档是直接写在 github 的 README 里,因为比较长,所以阅读和查找都非常不方便,于是就准备搞一个文档页面,考虑过使用 VuePress 之类的文档生成器,但我想把文档和 demo 做在一个项目里,所以都不太能满足我的需求,于是打算自己简单设计一个。

首先布局和常见的文档页面一样,上面标题栏,下面分为三部分,左侧是目录列表,中间是文档,右侧是文档的标题列表。

然后支持国际化,因为早期就有人帮我把文档翻译成了英文。

基本实现原理是每种语言一个文件夹,文件夹内是文档,文档用 markdown 来编写,写完后通过 Node.js 使用markdown-it + highlight.js 编译成 html ,最后再拼接成 Vue 单文件:

image-20230720112925872.png

为了在文档里实现在线预览的功能,我还使用了@vue/repl,因为它是把代码数据存储在 url 里,所以很方便,只要使用 iframe 嵌入就 url 就可以了。

接下来就是用 nodejs 遍历文档目录,根据一定规则生成路由列表:

image-20230720141442131.png

最后再把这个路由列表添加到 VueRouter 里即可,实现很简单,效果也不错:

image-20230720142241513.png

定位的转变

最开始的定位是一个纯 js 库,用于帮助和加快思维导图功能的开发,但是在线 demo 功能其实也很完整,当做一个思维导图工具来使用也是完全没有问题的,同时也确实有人在直接用它,于是我就慢慢的去除了贴在它上面的 demo 标签,把项目分成了两部分:

image-20230720143444856.png

虽然目前市面上思维导图的产品很多,百度一下会发现有非常多的选择,但是商业产品,即使最初免费,最终往往也会走向收费,或者对免费版各种限制,要么就是走向倒闭。所以我相信做一个开源的思维导图工具是有一定价值的,即使相比商业软件,有些功能无法实现,比如云端同步、在线协作、手机 APP 等,但是思维导图场景,做一个单机软件也是完全可以接受的。

然后考虑到目前在线版是运行在 github page上,国内访问可能有点慢,同时数据是保存在浏览器的 localStorage 里,如果图片多了,那么是很容易超出存储限制的,于是我就花了几天时间来入门 Electron,最后做了一个简单的客户端,实现过程可以移步这篇文章我的第一个Electron应用

最后,为了看着更正式一点,我又做了一个首页:

image-20230720144505481.png

其实还想过买一个域名,租个服务器,但是要花钱的事情,想了想还是算了,毕竟这个项目可能连这个成本都收不回来。

推广

等到功能差不多稳定了,就会想推广的事情,毕竟做了一个自己觉得不错的东西,还是希望能有更多人能看到和使用,另外就是酒香也怕巷子深,不主动去推广,那肯定没啥人知道,有时看到 github 里其他一些开源的思维导图库,它们有那么多星星,我就很羡慕,虽然各方面都不输它们,但是实际情况就是如此。

关于推广,我实在是没啥好的经验和途径,只做了这些:一是产出思维导图相关的文章,比如遇到一些实现难点或有意思的功能点时会写篇文章,然后发到各个技术社区;二是写纯广告文,发到我的公众号,然后朋友圈分享一下;最后就是去问答社区在思维导图相关的问题下进行推荐。

这些操作下来,效果非常有限。目前想到的就是看看能不能去一些英文社区推荐推荐,如果有这方面经验的朋友,欢迎评论区分享一下~

现状

接下来说一下目前的现状和各项数据,这个项目到目前为止,维护了差不多两年时间,目前一共提交了 500 多次代码,核心库代码量差不多有 1 万多行,star 数量 500 不到,issue 数量 150 多,pr 差不多是 10 个,然后贡献者除了我是 5 个,搞了个交流群,目前有 100 多人,在线版访问次数和客户端下载次数目前没办法统计,最后 npm 的总下载次数是 11000 多次:

image-20230720151452561.png

这个数据虽然非常普通,但也是我所有开源的项目里数据最好的了。

短期的目标是希望 star 数量能到 1k,可能短期也完不成,长期的目标是希望能做成开源界最好的思维导图,不得不说,野心挺大。

收获

技术

技术方面很难量化,你要说它具体给我带来了什么帮助,其实我也说不出来,但是确实比我在公司做的项目要难上很多,很多功能点实现起来也是有点难度的,比如各种布局结构的算法,尤其是鱼骨图,前后做了好几次才做出来,比如一直困扰我的性能优化的问题,比如节点编辑、键盘导航、关联线、支持各种格式的导入导出、在 canvas 中模拟 css 背景属性等等,很多看着简单的功能,实现起来其实都不简单。

所以能给我带来些许安慰,安慰自己是一个有一些能力和技术追求的前端,没有纯粹的混吃等死。

对于找工作的帮助

如果放在前几年可能对于找工作是有一点帮助的,但是目前的环境,它确实没啥帮助,大部分仍旧是已读不回,即使在面试过程中,虽然我表达出了这个项目其实比公司的项目更复杂,但是面试官仍然更想了解在公司所做的项目,公司的项目简单是客观现实,很多时候想通过这些开源的东西来给自己加分,但是基本盘不行,其实也改变不了结局,所以还是要想办法挖掘公司项目的亮点。

另外即使你东西做的好,你也得表达的好才行,于我而言,东西就摆在这里,代码、demo,你完全可以看的到,但是于面试官而言,他可能并没有那么多时间去看,很多东西在他眼里也并不难,所以你得清晰的表达出你的东西的亮点和难点,因为大部分时候,你表达不出来,那就相当于没有。

¥收益

绝大部分的开源项目想要赚钱我觉得都是很困难的,所以我也没抱什么期望,但是目前我也在 README 和文档上挂了打赏的二维码,还是有一些热心的朋友,偶尔喝杯咖啡的钱还是够的。

其实这也是我想推广的原因之一,毕竟用户基数大了了,愿意给你打赏的人的比例肯定也会增加。

心得

最后就是一些琐碎的心得。

1.翻译真的很累,目前基本上是使用机翻,即使这样我也觉得累,以后再也不吐槽其他开源项目没有中文翻译了。

2.不要把用户想的什么都知道,以前总觉得为什么其他产品的帮助文档要写的这么详细,明明很多一看就知道的功能也要写,但实际上,很多人他就是不知道,比如 Windows 系统该下载什么后缀名的文件,Mac 系统该下载什么,有人他就是不知道,所以不要想当然,有精力的情况下还是尽量要完善文档,除了开发文档,使用文档也是必不可少的。

3.很多问题没做之前觉得很复杂,等你开始做,发现是有点难度,但其实远远没有你想象的那么难,比如小地图、关联线、节点形状、Xmind 格式导入导出等等,最开始都觉得好复杂,不想做不想做,最后做出来发现也就这样,所以勇敢的迈出第一步把。

4.很多问题当时想不出来,怎么都想不出来,不妨放一放,过一段时间再来做,你会发现可能会突然灵光乍现,然后就顺利解决了,比如性能优化、鱼骨图的实现等等,我都是尝试一次做不出来,那就过段时间再试,因为短时间,你可能都是同一种思维,跳不出去,那么就很难解决。

5.开源项目的协议很重要,一定要显式的指定。

6.有些功能是要进行取舍的,比如最开始支持节点的过渡动画效果,也就是节点位置变化了是会移动过去,而不是直接闪现过去,但是一直有 bug 解决不了,就是快速操作的话,因为上一次节点的移动还没有结束,又开始下一次,导致节点位置错乱,这个问题尝试了很多次都无法彻底解决,于是最后就舍弃了,因为它只是一个锦上添花的功能,但是带来了显式的 bug ,那么还不如不要。

还有一个例子就是节点激活的样式,最开始所有样式都支持设置为激活的样式,包括一些会改变节点大小的样式,比如文字大小,这样会导致激活节点操作也要重新渲染节点所有内容,计算节点大小,调整其他节点位置,导致性能很差,全选非常慢,所以考虑过后,激活样式只允许修改不影响节点大小的属性,这样舍弃的只是一个不是很重要的功能,但是带来的好处是很明显的,现在全选非常的快。

7.一个人的力量是有限的,比如有一个问题我一直解决不了,就是以指定的中心点缩放画布,后来有一个网友他顺利帮我解决了,看他提交的代码其实很简单,但是自己想了多次就是想不出来,又比如一开始不支持导出 Xmind 文件,因为我尝试后发现 Xmind 文件解压缩后再压缩,Xmind 软件打不开,于是我想当然的认为是 Xmind 软件识别出了它是被解压缩过的,于是拒绝打开,后来群里有一个人就发现了原因是解压后不能再对文件夹进行压缩,而是要对文件进行压缩,所以不要小看合作的力量。

8.维护一个开源项目确实很耗费精力,你要解决和回答各种问题,千奇百怪,有些人上来就啪啪啪问你这个问你那个,明明有些问题只要多试一试,看一看文档就能知道,或者百度一下就能解决的问题,如果客气一点倒是也还好,但是有些人的语气就像你欠了他一样,我觉得这样不好,希望我们对待他人都能客气一点,虽然他做的东西他有一定义务,但是毕竟也会耗费他的一点时间,当然,如果你愿意先给他一点打赏,我相信他一定会很乐意解决你的问题。

以上。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Freeplane 思维导图软件中文版是由经典思维导图软件 FreeMind 的主创人员设计的另外一款同类型工具,Freeplane 已由官方翻译为中文,功能比较齐全,相较于 FreeMind 也毫不逊色。软件界面简洁明晰、操作方便快、设计的非常人性化,更重要的是它是免费的。当然博客上也提供的有其它的思维导图软件,比如:Xmind Pro 中文版,Mindmanage 中文版等等。 除了 SciPlore MindMapping,FreeMind 还有一个重要分支版本 FreePlane。该项目始于 2009 年 6 月,主要开发者是 Dimitry Polivaev,也是 FreeMind 开发者之一。FreePlane 在 FreeMind 基础上,增强了如下功能:更好的节点文字即席编辑、优化连接线、插入外部对象、脚本优化、全部文件替换、功能键工具栏、按住 control 和左键点击菜单项可修改热键、全屏模式、选择性粘贴、拼写检查、有结构的 html 粘贴。此外,还增强了过滤功能,并提供了多项其他改进。 开源思维导图 Freeplane 中文版开源思维导图 Freeplane 中文版 Freeplane 是一个免费的开源软件应用程序,支持在工作,学校和家庭中思考,分享信息和完成工作。 该软件可用于思维导图和分析思维导图中包含的信息。Freeplane 在任何具有安装当前Java版本的操作系统上运行。 它可以从可移动存储(如USB驱动器)本地或可移植地运行。 应用领域 Freeplane 比传统的思维导图支持更多。在导图的中心,应用程序区域可以看到导图的中心主题(根节点)。从它扩展是具有子主题(子节点)的分支。在边界,你会看到独立于根树的免费主题(自由节点)。所有主题都可以格式化或风格化,可以包含文字,超链接,图片等;并且可以用标记的线或箭头连接。另外,一个主题(节点)可以表示当用户想要或可以自动执行时显示的隐藏信息(公式)。内容也可以受密码保护或连接到特定的时间或过滤器。 Freeplane 支持上述应用领域,具有以下功能: 注意使用可自由定位的,未连接的节点(如post-it); 将节点(节点)排列成通过线(边)连接的层次结构; 使用元数据(属性)和样式类型(系统样式,用户定义的样式,级别样式)分类节点; 使用可视容器(云)和荣誉(摘要节点)对节点进行分组; 连接动态链接节点,免费线路(连接器)和标签; 根据层次和内容(条件样式,自动边缘颜色,级别样式)自动设置节点(具有气泡,颜色,边缘类型等); 在内容(文本,科学公式,计算,图标,图像和超链接)和演示区域(核心,细节,注释,属性,图像和工具提示)方面构建节点; 通过隐藏内容(折叠分支,过滤,汇总细节和在工具提示中隐藏扩展)来更改视图,查找,滚动和导航; 任务与日历和提醒; 使用DES加密对整个地图和个别节点进行密码保护; 易于使用内联和对话编辑器,面向对象的主菜单,上下文菜单,多语言支持,拼写检查器,属性面板,拖放功能,热键,批量执行选项,发布,共享和可选择的偏好; 即使没有完全匹配(例如“setup”=“设置”或“flie”=“文件”),大概搜索(相似性搜索)可以在文本中找到搜索词。 支持节点下面的LaTeX公式 轻松扩展附加功能和自制脚本; 与Docear学术文献套装整合; 通过Wiki和论坛的广泛支持;以及思维导图形式的教程和文档。 Freeplane 功能的地图说明了 Freeplane 的主要功能。此外,它提供了一个索引,其中包含教程的超链接,您可以在其中阅读更多内容。链接首先被隐藏,但变得可见,并且如果您将鼠标悬停在功能(节点)上,则可以单击链接。这是Freeplan的力量的另一个例子。 (要体验这些功能,请在“Freeplane程序”中打开“帮助”>“入门”,然后选择“索引”)。 附加组件和脚本 可以使用附加组件和脚本来扩展 Freeplane 的功能。您可以使用内置的脚本语言Groovy(基于JavaScript)制作自己的附加组件和脚本,并以1.5版本的其他语言(如python)开始。检查页面Add-ons_(安装)其他用户已经和共享的附加组件。它们可以通过简单的鼠标点击下载并安装。 如果您想制作自己的附加组件,可以使用说明。 提出思维导图 一旦你有一个思维导图,你可能想使用和呈现它。 RoAn-Presentation使用自动过滤和缩放功能,将思维导图与Powerpoint和Prezi类似的呈现组合在一起。 演示不仅展开节点,还显示隐藏的细节,使当前节点居中。 简而言之,它支持遍历思维导图,从用户那里获取丰富的点击。 您可以在这里下载并
在Android中,可以使用第三方库来实现思维导图的功能。其中比较常用的是Mindorks的Mindorks-Android-MindorksEditor库。 该库提供了一个自定义View来呈现思维导图,并且支持添加/删除节点、拖动节点、缩放、导入/导出等功能。 以下是使用该库实现思维导图的步骤: 1. 在build.gradle中添加依赖 ```groovy implementation 'com.mindorks.android:mindorks-editors:1.0.3' ``` 2. 在布局文件中添加MindorksEditorView ```xml <com.mindorks.editors.MindorksEditorView android:id="@+id/editorView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 在代码中初始化MindorksEditorView,并设置节点的点击事件、添加/删除节点的监听器等 ```java MindorksEditorView editorView = findViewById(R.id.editorView); editorView.setNodeClickListener(new NodeClickListener() { @Override public void onNodeClick(Node node) { // 节点点击事件处理 } }); editorView.setNodeAddListener(new NodeAddListener() { @Override public void onNodeAdd(Node node) { // 新增节点处理 } }); editorView.setNodeDeleteListener(new NodeDeleteListener() { @Override public void onNodeDelete(Node node) { // 删除节点处理 } }); ``` 4. 根据需要设置MindorksEditorView的属性,如节点颜色、边框颜色、字体大小等 ```java editorView.setNodeColor(Color.GREEN); editorView.setNodeBorderColor(Color.BLACK); editorView.setNodeTextSize(20); ``` 5. 可以使用MindorksEditorView提供的导入/导出方法,将思维导图保存为json文件或从json文件中读取 ```java editorView.exportToFile("path/to/file.json"); editorView.importFromFile("path/to/file.json"); ``` 以上是使用Mindorks-Android-MindorksEditor库来实现思维导图的基本步骤。需要注意的是,该库仅提供了基本的功能,如果需要实现更复杂的操作,可能需要自定义View来实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值