【javascript】纯原生js的轻便组织结构图,树状图,支持自定义样式
前言
写这个插件呢,只是一时兴起,公司的项目中使用到了组织结构图,然后本着面向百度、谷歌编程的思想,我去摸索了半天。
结果一无所获,可能这个词用的有点重了,但是就是没有符合我公司项目要求的,然后我又去了全球最大的同性社交网站(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,到此节点就全部渲染出来了,渲染出来后,就根据之前说的 id 和 fid 去绘制两点之间的连线,方法如下:
// 绘制节点之间的连线
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// 找到两点之间的中心点和关系就可以连线了// 具体代码就省略了,可以看源码......
}
到此,插件主要的思路和实现方法都介绍完了,剩下的就是把他们组合起来,并且支持自定义样式了,具体的就不在此展开了。
插件已经上传 github 和 npm 可以点击传送门查看。
github: https://github.com/Liyunkun11/mini-tree-map
npm: https://www.npmjs.com/package/mini-tree-map
总结
- 目前只定义了文本的节点,如果想新增可以在 calssName 上新增类名,根据类名自定义样式
- 渲染方向目前只支持两种,横向(horizontal)和竖向(vertical)
- 在 vue 中使用的时候建议用 npm 安装方式,并且在 mounted 生命周期中实例化
- 其他方式直接引入对应的 js 文件,然后直接调用实例化方法就可以
- 目前尚存在一些问题,空闲时间会想办法解决,浏览器兼容性未测试,主流皆可以
- 写这个只是自己的项目用到了,然后自己就想着封装了一个,欢迎大家提建议完善
【javascript】纯原生js的轻便组织结构图,树状图,支持自定义样式相关推荐
- d3.js v3版本实现-树状图
参考的例子:http://bl.ocks.org/robschmuecker/7880033 一.为什么选择d3.js 二.d3.js概述 三:树状图实现 1.创建svg 2.在svg元素里面画一个g ...
- react 原生html 插件,纯原生JS的瀑布流插件Macy.js,前端必备插件
这是一款非常轻量级的纯原生JS的瀑布流插件--Macy.js,如今图片和视频网站非常多,非常适应瀑布流这样的布局方式来呈现给用户. 所以,选择一款简单易用的瀑布流js插件,可以让前端工程师快速开发出漂 ...
- 扫雷html5简单初级,纯原生JS用面向对象class方法实现简易扫雷小游戏
Demo介绍 纯原生js 实现 且用ES6语法class写的扫雷小游戏:布局为10*10的网格,随机生成10-20个雷. 左键点击扫雷.右键标记该地方有雷.该demo下载下来复制到html文件中直接可 ...
- html5 原生插件,前端必备插件之纯原生JS的瀑布流插件Macy.js
这是一款非常轻量级的纯原生JS的瀑布流插件--Macy.js,如今图片和视频网站非常多,非常适应瀑布流这样的布局方式来呈现给用户. 这款流布局JS插件仅有4KB的大小,可以说是非常轻量级的哦.配置也比 ...
- 纯原生JS用面向对象class方法实现简易扫雷小游戏
Demo介绍 纯原生js 实现 且用ES6语法class写的扫雷小游戏:布局为10*10的网格,随机生成10-20个雷. 左键点击扫雷.右键标记该地方有雷.该demo下载下来复制到html文件中直接可 ...
- html手机页面选项卡,移动端网页纯原生js选项卡tab切换
适合移动网页纯原生js选项卡tab切换 *{ margin: 0; padding: 0} ul,li{ list-style: none} .tabClick{ background: #f3f3f ...
- 原生JS制作自动+手动轮播图,附带二级分类菜单
原生JS制作自动+手动轮播图,附带二级分类菜单 包含以下功能: 1.鼠标移开自动轮播 2.鼠标移入停止自动轮播 3.点击左右按钮可手动切换图片 4.点击索引小圆点可手动切换图片 5.鼠标移入一级菜单展 ...
- 原生JS实现韩雪冬轮播图
分享一个用原生JS实现的韩雪冬轮播图,效果如下: 实现代码如下: <!DOCTYPE html> <html><head lang="en">& ...
- 2021年原生JS实现韩雪冬轮播图
<!DOCTYPE html> <html><head lang="en"><meta charset="UTF-8" ...
最新文章
- 史上最强 NIO 框架,没有之一!!!
- pandas DataFrame 写入excel是列表 读取变字符串的解决办法
- 架构师之路 — 分布式系统 — Protocol Buffers 序列化协议
- 获取最大轮廓 opencv
- python多线程队列爬虫流程图_python 多线程爬虫 队列queue问题。
- AE 中的查找与定位,以城市查找为例
- pc和移动端获取滚动条的位置
- 关注电子商务网站中的消费信赖和消费安全感
- python协程,asyncIO
- atitit.软件设计模式大的总结attialx总结
- C++ OpenCV制作九宫格拼图游戏
- 省市县三级数据联动 -Java
- 贪吃蛇游戏 js网页版
- OSChina 周二乱弹 —— 我的手机指纹解锁和别人不一样
- PostgreSQL对不足位数的查询结果进行前后补0
- svn多分支合并主干冲突 svn Working copy and merge source not ready for reintegration
- 大学计算机基础实验3word表格,实验3word2010制作表格和插入对象土木2班滕成(1)
- 高通平台读取USB ID
- 台式计算机系统重新安装软件,教你台式机如何重装系统
- IB课程必修课TOK到底有啥用?