我需要的树状图需要那个节点可以做成div,里面展示不同信息,同时可以添加点击事件
但我看了echarts/ highcharts / d3 等等都是只能用 text,不能像我想要的那样做div然后自定义内容等等。
我是不是要自己写这个组件才行了呢??
https://www.jianshu.com/p/62dc49f1a7a1
https://www.jianshu.com/p/10684ce1ca0c
d3:https://observablehq.com/@d3/tidy-tree
echarts:https://echarts.apache.org/examples/zh/editor.html?c=tree-polyline
antV:https://g6.antv.vision/zh/examples/case/treeDemos#decisionTree
d3 案例
D3 纵向组织结构树
https://www.jianshu.com/p/dbe017596cc5
在 d3 中找到类似的例子,但是发现是主要在处理数据上做文章
https://observablehq.com/@didoesdigital/3-june-2020-d3-tree-diagram-and-d3-hierarchy
<template>
<div id="tree">
<svg></svg>
{{aaa}}
</div>
</template>
<script>
import * as d3 from 'd3' //引入d3
import { districtMockRes3 } from '@/assets/mockResponse/districtManagement.js'
export default {
name: 'customerManagement',
data() {
return {
textB: districtMockRes3,
aaa: ''
}
},
mounted() {
this.drawTree2()
},
methods: {
// tree2
drawTree2() {
let width = 954
let margin = { top: 48, right: 0, bottom: 48, left: 0 }
let dx = 12
let dy = 120
const tree = (data) => {
const root = d3.hierarchy(data)
root.dx = 10
root.dy = width / (root.height + 1)
return d3.tree().nodeSize([root.dx, root.dy])(root)
}
// const tree = d3.tree().nodeSize([dx, dy])
const treeLink = d3
.linkHorizontal()
.x((d) => d.y)
.y((d) => d.x)
function data(data) {
function populate(tree, words) {
if (words.length === 0) {
// condition for ending recursion
return
}
let word = words[0] // words = ["A", "bad", "excuse", "is", "better", "than", "none."]
let node = tree['children'].find((t) => t.text === word)
if (!node) {
// if we haven't seen this word before
node = {
text: word,
children: [],
}
tree['children'].push(node)
}
populate(node, words.slice(1)) // keep populating without the first, already-processed word
}
let root = {
text: '💬',
children: [],
}
let i = 0
const len = data.length
for (i; i < len; i++) {
const phrase = data[i] // "A bad excuse is better than none."
const words = phrase.split(' ') // ["A", "bad", "excuse", "is", "better", "than", "none."]
populate(root, words)
}
return root
}
this.aaa = data(this.textB)
let parsed = d3.hierarchy(this.textA, (id) => {
for (const split of [/[^\w\s]/, /\s/]) {
const children = id && id.split(split).filter((id) => id.length > 0)
if (children.length > 1) return children
}
})
function graph(root, { label = (d) => d.data.id, highlight = () => false, marginLeft = 40 } = {}) {
root = tree(root)
let x0 = Infinity
let x1 = -x0
root.each((d) => {
if (d.x > x1) x1 = d.x
if (d.x < x0) x0 = d.x
})
let svg = d3.select('#tree').select('svg')
svg
.style('background', 'yellow')
.attr('viewBox', [0, 0, width, x1 - x0 + dx * 2])
.style('overflow', 'visible')
const g = svg
.append('g')
.attr('font-family', 'sans-serif')
.attr('font-size', 10)
.attr('transform', `translate(${marginLeft},${dx - x0})`)
const link = g
.append('g')
.attr('fill', 'none')
.attr('stroke', '#555')
.attr('stroke-opacity', 0.4)
.attr('stroke-width', 1.5)
.selectAll('path')
.data(root.links())
.join('path')
.attr('stroke', (d) => (highlight(d.source) && highlight(d.target) ? 'red' : null))
.attr('stroke-opacity', (d) => (highlight(d.source) && highlight(d.target) ? 1 : null))
.attr('d', treeLink)
const node = g
.append('g')
.attr('stroke-linejoin', 'round')
.attr('stroke-width', 3)
.selectAll('g')
.data(root.descendants())
.join('g')
.attr('transform', (d) => `translate(${d.y},${d.x})`)
// node
// .append('circle')
// .attr('fill', (d) => (highlight(d) ? 'red' : d.children ? '#555' : '#999'))
// .attr('r', 2.5)
node.append('rect').attr('fill', (d) => (highlight(d) ? 'red' : d.children ? '#555' : '#999'))
// .attr('r', 2.5)
node
.append('text')
.attr('fill', (d) => (highlight(d) ? 'red' : null))
.attr('dy', '0.31em')
.attr('x', (d) => (d.children ? -6 : 6))
.attr('text-anchor', (d) => (d.children ? 'end' : 'start'))
.text(label)
.clone(true)
.lower()
.attr('stroke', 'white')
return svg.node()
}
graph(this.aaa, {
marginLeft: 200,
label: (d, i) => {
const { data } = d
return data.text
},
})
},
},
}
</script>
上面案例中 districtMockRes3
数据 如下
src/assets/mockResponse/districtManagement.js 文件下
export const districtMockRes3 = [
'A bad excuse is better than none.',
'A bad penny always turns up.',
'A bad workman blames his tools.',
'A bird in the hand is worth two in the bush.',
'A cat may look at a king.',
'A chain is only as strong as its weakest link.',
"A dog is a man's best friend.",
'A fool and his money are soon parted.',
'A friend in need is a friend indeed.',
'A journey of a thousand miles begins with a single step.',
'A little learning is a dangerous thing.',
'A leopard cannot change its spots.',
'A mill cannot grind with the water that is past.',
'A miss is as good as a mile.',
'A new language is a new life.',
'A penny saved is a penny earned.',
'A picture is worth a thousand words.',
'A rising tide lifts all boats.',
'A rolling stone gathers no moss.',
'A stitch in time saves nine.',
'A watched man never plays.',
'A watched pot never boils.',
'Absence makes the heart grow fonder.',
'Absolute power corrupts absolutely.',
'Accidents will happen in the best-regulated families.',
'Actions speak louder than words.',
'Adversity makes strange bedfellows.',
'All good things come to he who waits.',
'All good things must come to an end.',
'All hands on deck the pump.',
'All is grist that comes to the mill.',
'All roads lead to Rome.',
'All that glitters is not gold.',
'All the world loves a lover.',
'All things come to those who wait.',
'All things must pass.',
'All work and no play makes Jack a dull boy.',
'All you need is love.',
'All is fair in love and war.',
'All is for the best in the best of all possible worlds.',
'All is well that ends well.',
'An apple a day keeps the doctor away.',
'An army marches on its stomach.',
'An eye for an eye makes the whole world blind.',
"An Englishman's home is his castle.",
'Another day, another dollar.',
'An ounce of prevention is worth a pound of cure.',
'Any port in a storm.',
'Any publicity is good publicity.',
'April showers bring forth May flowers.',
'As you make your bed, so you must lie upon it.',
'As you sow so shall you reap.',
'Ask a silly question and you will get a silly answer.',
'Ask my companion if I be a thief.',
'Ask no questions and hear no lies.',
'Attack is the best form of defense.',
]
最后经过以下方法得到数据
function data(data) {
function populate(tree, words) {
if (words.length === 0) {
// condition for ending recursion
return
}
let word = words[0] // words = ["A", "bad", "excuse", "is", "better", "than", "none."]
let node = tree['children'].find((t) => t.text === word)
if (!node) {
// if we haven't seen this word before
node = {
text: word,
children: [],
}
tree['children'].push(node)
}
populate(node, words.slice(1)) // keep populating without the first, already-processed word
}
let root = {
text: '💬',
children: [],
}
let i = 0
const len = data.length
for (i; i < len; i++) {
const phrase = data[i] // "A bad excuse is better than none."
const words = phrase.split(' ') // ["A", "bad", "excuse", "is", "better", "than", "none."]
populate(root, words)
}
return root
}
得到数据如下
{
text: '💬',
children: [
{
text: 'A',
children: [
{
text: 'bad',
children: [
{
text: 'excuse',
children: [
{
text: 'is',
children: [
{
text: 'better',
children: [
{
text: 'than',
children: [
{
text: 'none.',
children: [],
},
],
},
],
},
],
},
],
},
{
text: 'penny',
children: [
{
text: 'always',
children: [
{
text: 'turns',
children: [
{
text: 'up.',
children: [],
},
],
},
],
},
],
},
{
text: 'workman',
children: [
{
text: 'blames',
children: [
{
text: 'his',
children: [
{
text: 'tools.',
children: [],
},
],
},
],
},
],
},
],
},
{
text: 'bird',
children: [
{
text: 'in',
children: [
{
text: 'the',
children: [
{
text: 'hand',
children: [
{
text: 'is',
children: [
{
text: 'worth',
children: [
{
text: 'two',
children: [
{
text: 'in',
children: [
{
text: 'the',
children: [
{
text: 'bush.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'cat',
children: [
{
text: 'may',
children: [
{
text: 'look',
children: [
{
text: 'at',
children: [
{
text: 'a',
children: [{ text: 'king.', children: [] }],
},
],
},
],
},
],
},
],
},
{
text: 'chain',
children: [
{
text: 'is',
children: [
{
text: 'only',
children: [
{
text: 'as',
children: [
{
text: 'strong',
children: [
{
text: 'as',
children: [
{
text: 'its',
children: [
{
text: 'weakest',
children: [
{
text: 'link.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'dog',
children: [
{
text: 'is',
children: [
{
text: 'a',
children: [
{
text: "man's",
children: [
{
text: 'best',
children: [
{
text: 'friend.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'fool',
children: [
{
text: 'and',
children: [
{
text: 'his',
children: [
{
text: 'money',
children: [
{
text: 'are',
children: [
{
text: 'soon',
children: [
{
text: 'parted.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'friend',
children: [
{
text: 'in',
children: [
{
text: 'need',
children: [
{
text: 'is',
children: [
{
text: 'a',
children: [
{
text: 'friend',
children: [
{
text: 'indeed.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'journey',
children: [
{
text: 'of',
children: [
{
text: 'a',
children: [
{
text: 'thousand',
children: [
{
text: 'miles',
children: [
{
text: 'begins',
children: [
{
text: 'with',
children: [
{
text: 'a',
children: [
{
text: 'single',
children: [
{
text: 'step.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'little',
children: [
{
text: 'learning',
children: [
{
text: 'is',
children: [
{
text: 'a',
children: [
{
text: 'dangerous',
children: [
{
text: 'thing.',
children: [],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'leopard',
children: [
{
text: 'cannot',
children: [{ text: 'change', children: [{ text: 'its', children: [{ text: 'spots.', children: [] }] }] }],
},
],
},
{
text: 'mill',
children: [
{
text: 'cannot',
children: [
{
text: 'grind',
children: [
{
text: 'with',
children: [
{
text: 'the',
children: [
{
text: 'water',
children: [
{
text: 'that',
children: [{ text: 'is', children: [{ text: 'past.', children: [] }] }],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'miss',
children: [
{
text: 'is',
children: [
{
text: 'as',
children: [
{
text: 'good',
children: [
{ text: 'as', children: [{ text: 'a', children: [{ text: 'mile.', children: [] }] }] },
],
},
],
},
],
},
],
},
{
text: 'new',
children: [
{
text: 'language',
children: [
{
text: 'is',
children: [{ text: 'a', children: [{ text: 'new', children: [{ text: 'life.', children: [] }] }] }],
},
],
},
],
},
{
text: 'penny',
children: [
{
text: 'saved',
children: [
{
text: 'is',
children: [
{ text: 'a', children: [{ text: 'penny', children: [{ text: 'earned.', children: [] }] }] },
],
},
],
},
],
},
{
text: 'picture',
children: [
{
text: 'is',
children: [
{
text: 'worth',
children: [
{ text: 'a', children: [{ text: 'thousand', children: [{ text: 'words.', children: [] }] }] },
],
},
],
},
],
},
{
text: 'rising',
children: [
{
text: 'tide',
children: [{ text: 'lifts', children: [{ text: 'all', children: [{ text: 'boats.', children: [] }] }] }],
},
],
},
{
text: 'rolling',
children: [
{
text: 'stone',
children: [{ text: 'gathers', children: [{ text: 'no', children: [{ text: 'moss.', children: [] }] }] }],
},
],
},
{
text: 'stitch',
children: [
{
text: 'in',
children: [{ text: 'time', children: [{ text: 'saves', children: [{ text: 'nine.', children: [] }] }] }],
},
],
},
{
text: 'watched',
children: [
{ text: 'man', children: [{ text: 'never', children: [{ text: 'plays.', children: [] }] }] },
{ text: 'pot', children: [{ text: 'never', children: [{ text: 'boils.', children: [] }] }] },
],
},
],
},
{
text: 'Absence',
children: [
{
text: 'makes',
children: [
{
text: 'the',
children: [
{ text: 'heart', children: [{ text: 'grow', children: [{ text: 'fonder.', children: [] }] }] },
],
},
],
},
],
},
{
text: 'Absolute',
children: [
{ text: 'power', children: [{ text: 'corrupts', children: [{ text: 'absolutely.', children: [] }] }] },
],
},
{
text: 'Accidents',
children: [
{
text: 'will',
children: [
{
text: 'happen',
children: [
{
text: 'in',
children: [
{
text: 'the',
children: [{ text: 'best-regulated', children: [{ text: 'families.', children: [] }] }],
},
],
},
],
},
],
},
],
},
{
text: 'Actions',
children: [
{
text: 'speak',
children: [{ text: 'louder', children: [{ text: 'than', children: [{ text: 'words.', children: [] }] }] }],
},
],
},
{
text: 'Adversity',
children: [{ text: 'makes', children: [{ text: 'strange', children: [{ text: 'bedfellows.', children: [] }] }] }],
},
{
text: 'All',
children: [
{
text: 'good',
children: [
{
text: 'things',
children: [
{
text: 'come',
children: [
{
text: 'to',
children: [
{ text: 'he', children: [{ text: 'who', children: [{ text: 'waits.', children: [] }] }] },
],
},
],
},
{
text: 'must',
children: [
{
text: 'come',
children: [
{ text: 'to', children: [{ text: 'an', children: [{ text: 'end.', children: [] }] }] },
],
},
],
},
],
},
],
},
{
text: 'hands',
children: [
{
text: 'on',
children: [{ text: 'deck', children: [{ text: 'the', children: [{ text: 'pump.', children: [] }] }] }],
},
],
},
{
text: 'is',
children: [
{
text: 'grist',
children: [
{
text: 'that',
children: [
{
text: 'comes',
children: [
{ text: 'to', children: [{ text: 'the', children: [{ text: 'mill.', children: [] }] }] },
],
},
],
},
],
},
{
text: 'fair',
children: [
{
text: 'in',
children: [{ text: 'love', children: [{ text: 'and', children: [{ text: 'war.', children: [] }] }] }],
},
],
},
{
text: 'for',
children: [
{
text: 'the',
children: [
{
text: 'best',
children: [
{
text: 'in',
children: [
{
text: 'the',
children: [
{
text: 'best',
children: [
{
text: 'of',
children: [
{
text: 'all',
children: [
{ text: 'possible', children: [{ text: 'worlds.', children: [] }] },
],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'well',
children: [{ text: 'that', children: [{ text: 'ends', children: [{ text: 'well.', children: [] }] }] }],
},
],
},
{
text: 'roads',
children: [{ text: 'lead', children: [{ text: 'to', children: [{ text: 'Rome.', children: [] }] }] }],
},
{
text: 'that',
children: [
{
text: 'glitters',
children: [{ text: 'is', children: [{ text: 'not', children: [{ text: 'gold.', children: [] }] }] }],
},
],
},
{
text: 'the',
children: [
{
text: 'world',
children: [{ text: 'loves', children: [{ text: 'a', children: [{ text: 'lover.', children: [] }] }] }],
},
],
},
{
text: 'things',
children: [
{
text: 'come',
children: [
{
text: 'to',
children: [
{ text: 'those', children: [{ text: 'who', children: [{ text: 'wait.', children: [] }] }] },
],
},
],
},
{ text: 'must', children: [{ text: 'pass.', children: [] }] },
],
},
{
text: 'work',
children: [
{
text: 'and',
children: [
{
text: 'no',
children: [
{
text: 'play',
children: [
{
text: 'makes',
children: [
{
text: 'Jack',
children: [
{ text: 'a', children: [{ text: 'dull', children: [{ text: 'boy.', children: [] }] }] },
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'you',
children: [{ text: 'need', children: [{ text: 'is', children: [{ text: 'love.', children: [] }] }] }],
},
],
},
{
text: 'An',
children: [
{
text: 'apple',
children: [
{
text: 'a',
children: [
{
text: 'day',
children: [
{
text: 'keeps',
children: [
{ text: 'the', children: [{ text: 'doctor', children: [{ text: 'away.', children: [] }] }] },
],
},
],
},
],
},
],
},
{
text: 'army',
children: [
{
text: 'marches',
children: [{ text: 'on', children: [{ text: 'its', children: [{ text: 'stomach.', children: [] }] }] }],
},
],
},
{
text: 'eye',
children: [
{
text: 'for',
children: [
{
text: 'an',
children: [
{
text: 'eye',
children: [
{
text: 'makes',
children: [
{
text: 'the',
children: [
{
text: 'whole',
children: [{ text: 'world', children: [{ text: 'blind.', children: [] }] }],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: "Englishman's",
children: [
{
text: 'home',
children: [{ text: 'is', children: [{ text: 'his', children: [{ text: 'castle.', children: [] }] }] }],
},
],
},
{
text: 'ounce',
children: [
{
text: 'of',
children: [
{
text: 'prevention',
children: [
{
text: 'is',
children: [
{
text: 'worth',
children: [
{
text: 'a',
children: [
{
text: 'pound',
children: [{ text: 'of', children: [{ text: 'cure.', children: [] }] }],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'Another',
children: [{ text: 'day,', children: [{ text: 'another', children: [{ text: 'dollar.', children: [] }] }] }],
},
{
text: 'Any',
children: [
{
text: 'port',
children: [{ text: 'in', children: [{ text: 'a', children: [{ text: 'storm.', children: [] }] }] }],
},
{
text: 'publicity',
children: [{ text: 'is', children: [{ text: 'good', children: [{ text: 'publicity.', children: [] }] }] }],
},
],
},
{
text: 'April',
children: [
{
text: 'showers',
children: [
{
text: 'bring',
children: [
{ text: 'forth', children: [{ text: 'May', children: [{ text: 'flowers.', children: [] }] }] },
],
},
],
},
],
},
{
text: 'As',
children: [
{
text: 'you',
children: [
{
text: 'make',
children: [
{
text: 'your',
children: [
{
text: 'bed,',
children: [
{
text: 'so',
children: [
{
text: 'you',
children: [
{
text: 'must',
children: [
{
text: 'lie',
children: [{ text: 'upon', children: [{ text: 'it.', children: [] }] }],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'sow',
children: [
{
text: 'so',
children: [
{ text: 'shall', children: [{ text: 'you', children: [{ text: 'reap.', children: [] }] }] },
],
},
],
},
],
},
],
},
{
text: 'Ask',
children: [
{
text: 'a',
children: [
{
text: 'silly',
children: [
{
text: 'question',
children: [
{
text: 'and',
children: [
{
text: 'you',
children: [
{
text: 'will',
children: [
{
text: 'get',
children: [
{
text: 'a',
children: [{ text: 'silly', children: [{ text: 'answer.', children: [] }] }],
},
],
},
],
},
],
},
],
},
],
},
],
},
],
},
{
text: 'my',
children: [
{
text: 'companion',
children: [
{
text: 'if',
children: [
{
text: 'I',
children: [
{ text: 'be', children: [{ text: 'a', children: [{ text: 'thief.', children: [] }] }] },
],
},
],
},
],
},
],
},
{
text: 'no',
children: [
{
text: 'questions',
children: [
{
text: 'and',
children: [{ text: 'hear', children: [{ text: 'no', children: [{ text: 'lies.', children: [] }] }] }],
},
],
},
],
},
],
},
{
text: 'Attack',
children: [
{
text: 'is',
children: [
{
text: 'the',
children: [
{
text: 'best',
children: [
{ text: 'form', children: [{ text: 'of', children: [{ text: 'defense.', children: [] }] }] },
],
},
],
},
],
},
],
},
],
}