前言

写这个插件呢,只是一时兴起,公司的项目中使用到了组织结构图,然后本着面向百度、谷歌编程的思想,我去摸索了半天。

结果一无所获,可能这个词用的有点重了,但是就是没有符合我公司项目要求的,然后我又去了全球最大的同性社交网站(github)还是没有找到自己满意的插件。

但是整个过程借鉴下来也有了自己的一些小思路,干脆自己封装一个得了(本文的插件非常简单,大佬勿喷)

效果图

没图没真相,先放效果图

1.竖向渲染效果图

2.横向渲染效果图

在此就不放 gif 图了,节点皆可动态显示和隐藏,也支持自定义样式。

思路和实现

思路呢,大概是这样的,先定数据结构,因为有了结构才好拿着去定 dom 的结构。

因为是结构图嘛,所以父子关系肯定是跑不掉了,那基本的关系就如下了:

{body: {}, //这个代表当前节点children: [], //这个代表子节点
}

有人问那如果还有孙子节点怎么办?诶,问的好!那就开始套娃了(刚好方便后期递归渲染),所以结构如下:

{//这个代表当前节点body: {},//这个代表子节点children: [{//这个代表孙子节点body: {},...}],
}

ok,结构搞定以后,就去拿着生成 dom 吧,这里我简单写个了方法用来创建元素,省的每次都写一堆...

// 创建元素的方法
function createEl(tag, domStyle, domClass) {let _dom = document.createElement(tag);Object.assign(_dom.style, domStyle);if (domClass) _dom.className = domClass;return _dom;
}

是不是简单明了,传标签名、标签的内联样式、标签的类名就可以直接生成 dom 元素了。

搞定了创建元素的方法,在此基础上再去写一个创建节点的方法,把 body 里面的新增两个字段

1.content 代表当前节点的内容,为了让节点更丰富化所以这里支持富文本格式。

2.className 代表当前节点的类名,支持多个类名,用空格隔开就行。

有了这两个字段,基本上节点就具备基础的内容和类名了,创建节点方法如下:

// 创建节点方法
function createNode(body){let _body = body;let _node = createEl("div", {margin: "20px",padding: "10px",border: "1px solid #2288ff"boxSizing: "border-box",position: "relative",flexShrink: 0}, _body.className);_node.innerHTML = _body.content;return _node;
}

ok,现在创建元素和创建节点的方法都搞定了,下面就是要根据结构去渲染出来节点了,这里为了更直观的渲染出来结构,我使用了 flex 布局。

为了省事,这里直接贴递归渲染节点方法的思路,如下:

// 递归创建节点的方法
// data 是数据源、wrap是挂载的容器、id是后面用来表名父子关系的标识
let nodeNum = 0;
function renderNode(data,wrap,id){// 1.创建父元素节点let parentNode = createEl("div", { display: "flex", alignItems: "center", userSelect: "none" });// 2.创建当前元素节点let currentNode = createNode(data.body);// 注意这里每个节点上面都有属性 id 和 fid 就是为了后面表名父子关系的标识currentNode.setAttribute("data-id", ++nodeNum);currentNode.setAttribute("data-fid", id ? id : 0);// 添加公共类名,这里防止覆盖原有的类名,所以使用 classList.add 方法currentNode.classList.add("tree-map-node");// 3.是否给当前元素节点创建伸缩符if (!!data.shrink && !!data.children && data.children.length > 0){// 符合这个条件就渲染,然后父相子绝放到当前元素上面(记得绑定点击事件)......}// 4.创建子元素节点if (!!data.children && data.children.length > 0 && !data.hidden) {// 有子节点就走这个方法let childrenNode = createEl("div");parentNode.appendChild(currentNode);parentNode.appendChild(childrenNode);// 注意:因为是使用的递归(深度遍历优先)所以parentId需要根据DOM结构去取出来!let parentId = childrenNode.previousSibling.getAttribute("data-id");for (let index = 0; index < data.children.length; index++) {renderNode(data.children[index], childrenNode, parentId);}} else {// 没有就直接不创建子节点parentNode.appendChild(currentNode);}// 5.最后挂载到外部容器中wrap.appendChild(parentNode);}

ok,到此节点就全部渲染出来了,渲染出来后,就根据之前说的 idfid 去绘制两点之间的连线,方法如下:

// 绘制节点之间的连线
function drawline() {// 此处写你给每个节点起的公共类名let selector = ".tree-map-node";// 获取所有渲染出来的节点let treeNodes = document.querySelectorAll(selector);treeNodes.forEach(function (currentNode) {// 根据 fid 去选中他的父元素节点let parentNode = document.querySelector(".tree-map-node[data-id='" + currentNode.getAttribute("data-fid") + "']");if (parentNode) drawLineBetweenNode(parentNode, currentNode);})
}// 连接节点的方法
function drawLineBetweenNode(parentNode,childNode){// 这里根据offsetWidth、offsetHeight、offsetLeft、offsetTop// 找到两点之间的中心点和关系就可以连线了// 具体代码就省略了,可以看源码......
}

到此,插件主要的思路和实现方法都介绍完了,剩下的就是把他们组合起来,并且支持自定义样式了,具体的就不在此展开了。

插件已经上传 githubnpm 可以点击传送门查看。

github: https://github.com/Liyunkun11/mini-tree-map

npm: https://www.npmjs.com/package/mini-tree-map

总结

  1. 目前只定义了文本的节点,如果想新增可以在 calssName 上新增类名,根据类名自定义样式
  2. 渲染方向目前只支持两种,横向(horizontal)和竖向(vertical
  3. 在 vue 中使用的时候建议用 npm 安装方式,并且在 mounted 生命周期中实例化
  4. 其他方式直接引入对应的 js 文件,然后直接调用实例化方法就可以
  5. 目前尚存在一些问题,空闲时间会想办法解决,浏览器兼容性未测试,主流皆可以
  6. 写这个只是自己的项目用到了,然后自己就想着封装了一个,欢迎大家提建议完善

【javascript】纯原生js的轻便组织结构图,树状图,支持自定义样式相关推荐

  1. d3.js v3版本实现-树状图

    参考的例子:http://bl.ocks.org/robschmuecker/7880033 一.为什么选择d3.js 二.d3.js概述 三:树状图实现 1.创建svg 2.在svg元素里面画一个g ...

  2. react 原生html 插件,纯原生JS的瀑布流插件Macy.js,前端必备插件

    这是一款非常轻量级的纯原生JS的瀑布流插件--Macy.js,如今图片和视频网站非常多,非常适应瀑布流这样的布局方式来呈现给用户. 所以,选择一款简单易用的瀑布流js插件,可以让前端工程师快速开发出漂 ...

  3. 扫雷html5简单初级,纯原生JS用面向对象class方法实现简易扫雷小游戏

    Demo介绍 纯原生js 实现 且用ES6语法class写的扫雷小游戏:布局为10*10的网格,随机生成10-20个雷. 左键点击扫雷.右键标记该地方有雷.该demo下载下来复制到html文件中直接可 ...

  4. html5 原生插件,前端必备插件之纯原生JS的瀑布流插件Macy.js

    这是一款非常轻量级的纯原生JS的瀑布流插件--Macy.js,如今图片和视频网站非常多,非常适应瀑布流这样的布局方式来呈现给用户. 这款流布局JS插件仅有4KB的大小,可以说是非常轻量级的哦.配置也比 ...

  5. 纯原生JS用面向对象class方法实现简易扫雷小游戏

    Demo介绍 纯原生js 实现 且用ES6语法class写的扫雷小游戏:布局为10*10的网格,随机生成10-20个雷. 左键点击扫雷.右键标记该地方有雷.该demo下载下来复制到html文件中直接可 ...

  6. html手机页面选项卡,移动端网页纯原生js选项卡tab切换

    适合移动网页纯原生js选项卡tab切换 *{ margin: 0; padding: 0} ul,li{ list-style: none} .tabClick{ background: #f3f3f ...

  7. 原生JS制作自动+手动轮播图,附带二级分类菜单

    原生JS制作自动+手动轮播图,附带二级分类菜单 包含以下功能: 1.鼠标移开自动轮播 2.鼠标移入停止自动轮播 3.点击左右按钮可手动切换图片 4.点击索引小圆点可手动切换图片 5.鼠标移入一级菜单展 ...

  8. 原生JS实现韩雪冬轮播图

    分享一个用原生JS实现的韩雪冬轮播图,效果如下: 实现代码如下: <!DOCTYPE html> <html><head lang="en">& ...

  9. 2021年原生JS实现韩雪冬轮播图

    <!DOCTYPE html> <html><head lang="en"><meta charset="UTF-8" ...

最新文章

  1. 史上最强 NIO 框架,没有之一!!!
  2. pandas DataFrame 写入excel是列表 读取变字符串的解决办法
  3. 架构师之路 — 分布式系统 — Protocol Buffers 序列化协议
  4. 获取最大轮廓 opencv
  5. python多线程队列爬虫流程图_python 多线程爬虫 队列queue问题。
  6. AE 中的查找与定位,以城市查找为例
  7. pc和移动端获取滚动条的位置
  8. 关注电子商务网站中的消费信赖和消费安全感
  9. python协程,asyncIO
  10. atitit.软件设计模式大的总结attialx总结
  11. C++ OpenCV制作九宫格拼图游戏
  12. 省市县三级数据联动 -Java
  13. 贪吃蛇游戏 js网页版
  14. OSChina 周二乱弹 —— 我的手机指纹解锁和别人不一样
  15. PostgreSQL对不足位数的查询结果进行前后补0
  16. svn多分支合并主干冲突 svn Working copy and merge source not ready for reintegration
  17. 大学计算机基础实验3word表格,实验3word2010制作表格和插入对象土木2班滕成(1)
  18. 高通平台读取USB ID
  19. 台式计算机系统重新安装软件,教你台式机如何重装系统
  20. IB课程必修课TOK到底有啥用?

热门文章

  1. 第七章 项目成本管理
  2. DANN:Unsupervised Domain Adaptation by Backpropagation
  3. 数据库作业:关系数据库及相关概念
  4. 带你读论文系列之计算机视觉--GoogLeNet
  5. eclipse中ctrl+D失效的解决方案
  6. 分享快速检测肖特基二极管的小窍门
  7. TWaver 3D作品Viewer查看器
  8. sql char和varchar的区别
  9. 网站访问全过程涉及的网络协议详解
  10. Resnet18-cifar10及Million-AID数据加载