首页 > 其他分享 >使用js实现思维导图

使用js实现思维导图

时间:2023-07-24 17:07:34浏览次数:31  
标签:node 思维 startY 导图 js 垂直 坐标 节点


本文主要阐述使用js实现思维导图的关键技术点,如果还不知道什么是思维导图的同学,请自行度娘。以下是demo和源码的传送门:

demo:http://sources.ikeepstudying.com/mindmaptree-master/ 源码:http://github.com/RockyRen/mindmaptree/tree/master

下载:mindmaptree-master

 

在源码中我使用了svg绘制思维导图。与canvas相比,svg将图像当成对象,我们可将思维导图中节点和线等图形表现为对象,而且svg更适合用于动态交互的应用

 

下面介绍几个关键技术点:

 

子节点位置的重绘
一个基本的思维导图工具应该拥有增加节点和删除节点的功能。在某个节点上增删节点时,为了使得所有子节点的高度相对于该节点垂直居中,都会重新渲染子节点的垂直位置。
如图1所示,首先求得父节点的中心点F的坐标为(hfx, hfy),设父节点与子节点的水平距离为interval,父节点的宽为parentWidth。作水平线段FC,C点的横坐标即为子节点的横坐标childX。如下图所示:



使用js实现思维导图

为 了让子节点间垂直隔开,每一个子节点上下都有补白,所以一个子节点所占的区域高度为该子节点的节点高度加上两个补白高度。迭代所有子节点,求取所有子节 点的区域高度areaHeight,然后在线段FC的C点上作一条长度为areaHeight的垂直平分线AB,所有子节点的垂直区域都在垂直平分线AB 内,这样可以保证所有子节点的高度相对于该节点垂直居中。如下图所示:

 


使用js实现思维导图

我 们需要求得每一个子节点的垂直坐标childY。首先求得A点的垂直坐标startY = hfy – areaHeight / 2,第一个子节点的垂直坐标由startY加padding可得。求第二个子节点的垂直坐标时,startY累加上一个子节点的区域高度,则第二个子节点 的垂直坐标等于当前startY加上padding。之后的子节点通过迭代相同的操作可得。在每一轮迭代中,根据求得的子节点坐标(childX, childY)渲染节点的位置。如下图所示:


使用js实现思维导图

实现代码如下:


/ 以下变量请自行求得var hfx, // 父节点的中心x轴坐标hfy, // 父节点的中心y轴坐标parentWidth, // 父节点的宽度
children, // 子节点列表
padding, // 子节点垂直间距
interval; // 节点间水平间距
 
var childX, // 子节点的x轴坐标
startY, // 子节点区域的起始坐标
childrenAreaHeight = 0; // 子节点总区域高度
 
 
childX = hfx + parentWidth / 2 + interval;
 
// 迭代子节点,求得子节点总区域高度
children.forEach(function(child){
var curAreaHeight = getNodeHeight(child) + padding * 2;
childrenAreaHeight += curAreaHeight;
});
 
startY = hfy - childrenAreaHeight / 2;
// 迭代子节点,求得每个子节点的垂直坐标
children.forEach(function(child){
var childY = startY + padding;
 
// 已经求得当前子节点坐标(childX, childY),在这里作渲染操作
 
var curAreaHeight = getNodeHeight(child) + padding * 2;
startY += curAreaHeight;    // 其实高度累加
});
 
 
/**
* 获取节点的高度
*/
function getNodeHeight(){
// ...
}


 

祖先节点的同级节点的垂直位置调整
如下图所示,当增加一个节点时,该节点父节点的同级节点需要被“撑开”:设该节点的1/2区域高度为moveY,在父节点的同级节点中,比父节点高的向上 偏移一个moveY,比父节点低的向下偏移一个moveY。父节点的父节点的同级节点也做相同的处理,一直递归到根节点为止。当删除一个节点时,节点的父 节点的同级节点会被“压低”,“压低”操作和上述操作相似。注意,当增加第一个子节点和删除最后一个子节点时,不会进行“撑开”和“压低”操作。


使用js实现思维导图

实现源码如下:

/*** 调整当前的父节点的同级节点的位置* @param node 当前的父节点, 以下为该节点需要用到的属性*              node.father: 节点的父节点,为null时表示父节点为根节点*              node.children:  节点的子节点列表
*              node.x:  节点的x轴坐标
*              node.y: 节点的y轴坐标
*
* @oaram areaHeight 被操作节点的区域高度
*/
function resetBrotherPosition(node, areaHeight){
    var brother,                    // 同级节点
        moveY = areaHeight / 2;     // 需要移动的高度
    if(node.father){
        node.father.children.forEach(function(curNode){
                // 遍历同级节点
                if(curNode != node){
                    if(brother.y < node.y){
                        // 向上移动brother节点的代码写在这
                    }
                    else {
                        // 向下移动brother节点的代码写在这
                    }
                }
            }
        );
    }
    // 递归父节点
    if(node.father){
        resetBrotherPosition(node.father, areaHeight);
    }
}


 

拖动节点
当拖动根节点时,通过改变svg的视口坐标来实现拖动整个思维导图的效果。当拖动
非根节点时,会按顺序触发mouseup、mousemove、mousedown三个事件,分别对应按下鼠标、鼠标移动和放下鼠标三个状态。在按下鼠标 状态下,会以当前节点为原型克隆一个节点用于占位。在拖动鼠标状态下,通过改变节点的坐标实现节点位置的改变。在放下鼠标状态下,会判断当前节点是否与其 他节点重叠,如果重叠则使重叠节点变为当前节点的父节点,否则,当前节点返回原来的位置。

其他技术点我就不一一列出来了,有兴趣的同学可以到上面的传送门看看源码。


 

 

标签:node,思维,startY,导图,js,垂直,坐标,节点
From: https://blog.51cto.com/u_8895844/6836736

相关文章

  • PHP数组缓存:三种方式JSON、序列化和var_export的比较
    使用PHP的站点系统,在面对大数据量的时候不得不引入缓存机制。有一种简单有效的办法是将PHP的对象缓存到文件里。下面我来对这3种缓存方法进行说明和比较。第一种方法:JSONJSON缓存变量的方式主要是使用json_encode和json_decode两个php函数。json_encode可以将变量变成文本格式,这......
  • Converting between XML and JSON
    1ConvertionbetweenXMLandJSONhttp://www.json.org/java/index.html  API:http://www.json.org/javadoc/org/json/XML.htmlpublicclassXMLextendsjava.lang.Object ThisprovidesstaticmethodstoconvertanXMLtextintoaJSONObject,andt......
  • 【Azure Event Hub】Event Hub的Process Data页面无法通过JSON格式预览数据
    问题描述在EventHub的门户页面中,可以通过ProcessData页面查看EventHub中的数据,但是当使用JSON格式预览时(ViewinJSON),却出现错误。消息一: Nodatawasfoundforpreviewfrom'test01'.Makesuretheinputhasrecentlyreceiveddataandthecorrectformatofthosee......
  • jstl tags
    前言=========================================================================JSTL标签库,是日常开发经常使用的,也是众多标签中性能最好的。把常用的内容,放在这里备份一份,随用随查。尽量做到不用查,就可以随手就可以写出来。这算是Java程序员的基本功吧,一定要扎实。 JSTL全名为J......
  • 常见的js内存泄漏
    1、 意外的全局变量。未被声明的变量,会被挂在window对象下,不能及时的销毁。2、计时器和回调函数timers。定时器setInterval或者setTimeout在不需要使用的时候,没有被clear,导致定时器的回调函数及其内部依赖的变量都不能被回收,这就会造成内存泄漏。3、DOM泄漏。(1)给DOM对象添加的属......
  • 【js学习笔记五十二】weakmap的应用
     目录前言导语 代码部分前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很酷导语WeakuMap编辑 代码......
  • 【js学习笔记五十一】weakmap
     目录前言导语 代码部分前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很酷导语WeakMap编辑 代码部......
  • 面对对象还是基于对象傻傻分不清楚,JS这个非主流太搞了
    与其它的语言相比,JavaScript中的“对象”总是显得不那么合群。一些新人在学习JavaScript面向对象时,往往也会有疑惑:为什么JavaScript(直到ES6)有对象的概念,但是却没有像其他的语言那样,有类的概念呢;为什么在JavaScript对象里可以自由添加属性,而其他的语言却不能呢?甚至,在一些争论......
  • .net core controller获取post的json数据
    如何在.NETCoreController中获取POST的JSON数据在开发Web应用程序时,我们经常需要从客户端发送一些数据到服务器端。一种常见的方式是使用HTTP的POST方法来发送数据。在.NETCore中,我们可以使用Controller来处理这些请求,并从POST请求中获取JSON数据。创建一个.NETCoreWebAPI......
  • 在线java 实体转 json
    在线Java实体转JSON的步骤和代码示例1.简介在Java开发中,我们经常需要将Java对象转换为JSON格式,以便在网络传输或者存储过程中使用。在本文中,我将向你介绍如何在线进行Java实体转JSON的处理,并提供相应的代码示例。2.实体转JSON的步骤下面是实现在线Java实体转JSON的整个流程,通......