這是一個用js寫的簡易思惟腦圖, 大約用了100多行代碼,效果以下圖
差什麼功能小夥伴們能夠自行DIY一下,後期可能會補足這些功能!vue
我爲公司改過一版適用angular框架的,受限於angular render2,我在代碼中用了幾個setTimeout(),感受很不優雅,就不提供給小夥伴了。
純潔的js代碼,小夥伴能夠DIY給 angular
react
vue
框架!node
詳見下面代碼和代碼註釋
// typeScript 數據格式 // class Node { // title: string; // children: [Node]; // fontColor?: string = null; // borderColor?: string = null; // bgColor?: string = null; // } // mack 數據 const treeData = [ { title: '張海生', children: [ { title: "1.1", children: [ {title: "1.1.1"}, { title: "李1.1.2光", children: [ {title: "張1.1.2.1中"}, {title: "1.1.2.2"}, { title: "1.1.2.3", children: [ {title: "1.1.2.3,1"}, {title: "1.1.2.3.2"}, {title: "1.1.2.3.3"}, {title: "1.1.2.3.4"}, {title: "1.1.2.3.5"}, ] }, {title: "1.1.2.4"}, {title: "1.1.2.5"}, ] }, ] }, { title: "1.2", children: [ {title: "1.2.1",borderColor:"red",fontColor:"red"}, {title: "1.2.2",bgColor:"black",fontColor:"white"}, ] }, ] } ]; const nodeFontS = 14; // 字體大小 const interval = 25; // 節點左右間隔大小 const padding = 4; // 節點內部padding const margin_y = 6; // 節點上下margin const fontColor = "#626262"; // 默認字體顏色 const borderColor = "#55aaee"; // 默認邊框顏色 const lineColor = "#55aaee"; // 默認連線顏色 const svg = document.getElementById('svgContainer'); let _svgW = 0; let _lastNodeN = 0; const _nodeH = nodeFontS + padding * 2 + margin_y * 2; // 樹狀結構數據重構 reBuildData(treeData, null); buildSvg(treeData); setSvgContainerSize(_svgW+30, _lastNodeN * _nodeH + 30); console.log('treeData'); console.log(treeData); console.log(_lastNodeN); function reBuildData(d, parent) { //樹狀結構數據重構 d.forEach((v, i) => { v.parent = parent; if (v.children && v.children.length > 0) { reBuildData(v.children, v); parentY(v, d.length, i) } else { _lastNodeN = _lastNodeN + 1; v.y = _lastNodeN; parentY(v, d.length, i) } }) } function parentY(lastNode, len, i) { //計算節點的y座標 const parent = lastNode.parent; if (len === (i + 1) && !!parent) { const s = parent.children[0].y; parent.y = s + (lastNode.y - s) / 2 } } function setSvgContainerSize(w, h) { //設置svg的寬和高 svg.setAttribute("width", w); svg.setAttribute("height", h); } function buildSvg(data) { //生成腦圖svg data.forEach((v) => { buildNode(v); if (!!v.children && v.children.length > 0) { buildSvg(v.children) } }) } function buildNode(node) { // 構建腦圖的每一個節點 const gTag = document.createElementNS('http://www.w3.org/2000/svg', 'g'); const textTag = document.createElementNS('http://www.w3.org/2000/svg', 'text'); const text = document.createTextNode(node.title); textTag.appendChild(text); gTag.appendChild(textTag) svg.appendChild(gTag); textTag.setAttribute("fill", node.fontColor ? node.fontColor : fontColor); const parentx = !!node.parent ? node.parent.x : 0; const parentw = !!node.parent ? node.parent.w : 0; const intervalNow = !!node.parent ? interval : 0; const textH = Math.ceil(textTag.getBBox().height); node.w = Math.ceil(textTag.getBBox().width) + padding * 2; node.x = parentx + parentw + intervalNow + 6; gTag.setAttribute('transform', `translate(${node.x + padding},${node.y * (_nodeH) + textH / 2 - 5})`); if ((node.w + node.x) > _svgW) { _svgW = node.w + node.x; } gTag.insertBefore(drawBorder(node), textTag); drawLine(node); } function drawBorder(node){ //畫節點的邊框 const fan = document.createElementNS('http://www.w3.org/2000/svg', 'path'); fan.setAttribute("d", getBorderD(node)); fan.setAttribute('stroke', node.borderColor ? node.borderColor : borderColor); fan.setAttribute("stroke-width", "1"); fan.setAttribute("fill", node.bgColor?node.bgColor:"none"); return fan; } function getBorderD(node){ //得到節點的d return `M0,-17h${node.w-8}a5,5,0,0,1,5,5v13a5,5,0,0,1,-5,5h-${node.w-8}a5,5,0,0,1,-5,-5v-13a5,5,0,0,1,5,-5z` } function drawLine(node) { //爲當前節點連線父級節點 if (!node.parent) { return } const fan = document.createElementNS('http://www.w3.org/2000/svg', 'path'); svg.appendChild(fan); fan.setAttribute("d", getD(node)); fan.setAttribute('stroke', lineColor); fan.setAttribute("stroke-width", "1"); fan.setAttribute("fill", "none"); } function getD(node) { // 得到節點的 d線 const parent = node.parent; if (parent.y != node.y) { return `M${parent.x + parent.w} ${parent.y * _nodeH} C${parent.x + parent.w + 15} ${parent.y * _nodeH} ${node.x - 15} ${node.y * _nodeH} ${node.x} ${node.y * _nodeH}`; } else { return `M${parent.x + parent.w} ${parent.y * _nodeH} L${node.x} ${node.y * _nodeH}`; } }
複製過來不少字符前面被segmentfault加了轉譯字符,我手動刪除了,能夠會誤刪,要看源碼能夠去我GitHub上clone
github源碼 https://github.com/sure2darli...react