我正在使用d3.js尝试生成如图所示的图像。我想在图像下方附加链接标签。
如何绘制下面的图像?
下面是我的HTML来源
<svg id="mysvg" width="800" height="800">
<defs>
<marker id="arrow" markerUnits="strokeWidth" markerWidth="10" markerHeight="10" viewBox="0 0 12 12" refX="8.5" refY="5.8" orient="auto">
<path d="M2,2 L10,6 L2,10 L6,6 L2,2" style="fill: steelblue;"></path>
</marker>
</defs>
</svg>
下面是Javascript来源
var diameter = 900, radius = diameter / 2, innerRadius = radius - 150
var cluster = d3.cluster().size([360, innerRadius])
var line = d3.radialLine()
.curve(d3.curveBundle.beta(0.35))
.radius(function(d) { return d.y })
.angle(function(d) { return d.x / 180 * Math.PI })
var svg = d3.select('#mysvg')
.attr('marker-end', 'url(#arrow)')
.attr('width', diameter)
.attr('height', diameter)
.append('g')
.attr('transform', 'translate(' + radius + ',' + radius + ')')
var link = svg.append('g').selectAll('.link')
var node = svg.append('g').selectAll('.node')
d3.json("http://localhost:3000/flare").then(function(classes) {
var root = packageHierarchy(classes)
cluster(root)
link = link
.data(packageImports(root.leaves()))
.enter()
.append('path')
.each(function(d) {
d.source = d[0], d.target = d[d.length - 1]
})
.attr('class', 'link')
.attr('d', line)
node
.data(root.leaves())
.enter()
.append('text')
.attr('class', 'node')
.attr('dy', '0.31em')
.attr('transform', function(d) {
return 'rotate(' + (d.x - 90) + ')translate(' + (d.y + 8) + ',0)' + (d.x < 180 ? '' : 'rotate(180)')
})
.attr('text-anchor', function(d) {
return d.x < 180 ? 'start' : 'end'
})
.text(function(d) {
return d.data.key
})
.style('font-weight', 'bold')
.style('font-size', '16px')
.on('mouseover', mouseovered)
.on('mouseout', mouseouted)
.on('click', function () {
alert(1)
})
node.data(root.leaves())
.enter()
.append('text')
.attr('class', 'node')
.attr('dy', '0.31em')
.attr('transform', function(d) {
return 'rotate(' + (d.x - 93) + ')translate(' + (d.y + 8) + ',0)' + (d.x < 180 ? '' : 'rotate(180)')
})
.attr('text-anchor', function(d) {
return d.x < 180 ? 'start' : 'end'
})
.text(function(d) {
return '(' + d.data.totalCallCnt + ')'
})
.style('font-weight', 'bold')
.style('font-size', '13px')
.on('mouseover', mouseovered)
.on('mouseout', mouseouted)
.on('click', function () {
alert(1)
})
})
function mouseovered(d) {
node.each(function(n) {
n.target = n.source = false
})
link.classed('link--target', function(l) {
if (l.target === d)
return l.source.source = true
})
.classed('link--source', function(l) {
if (l.source === d)
return l.target.target = true
})
.filter(function(l) {
return l.target === d || l.source === d
})
.raise()
node.classed('node--target', function(n) {
return n.target
})
.classed('node--source', function(n) {
return n.source
})
}
function mouseouted(d) {
link
.classed('link--target', false)
.classed('link--source', false)
node
.classed('node--target', false)
.classed('node--source', false)
}
function packageHierarchy(classes) {
var map = { }
function find(name, data) {
var node = map[name], i
if (!node) {
node = map[name] = data || { name: name, children: [] }
if (name.length) {
node.parent = find(name.substring(0, i = name.lastIndexOf('.')))
node.parent.children.push(node)
node.key = name.substring(i + 1)
}
}
return node
}
classes.forEach(function(d) {
find(d.name || d.id, d)
})
return d3.hierarchy(map[''])
}
function packageImports(nodes) {
var map = {},
imports = []
nodes.forEach(function(d) {
map[d.data.name || d.data.id] = d
})
nodes.forEach(function(d) {
if (d.data.to) {
d.data.to.forEach(function(i) {
imports.push(map[d.data.name || d.data.id].path(map[i.name || i.id]))
})
}
})
return imports
}
,数据模型格式如下:
[
{
"id": "INIT",
"name": null,
"totalCallCnt": 0,
"toScenarios": [
{
"id": "SCNRF1P2P5NA11352363",
"name": "주문시나리오",
"cnt": 2
},
{
"id": "SCNRF31MKPOSAF9F5200",
"name": "123123",
"cnt": 24
},
{
"id": "SCNRF31MN1MO03A8A4EC",
"name": "ddd",
"cnt": 3
},
{
"id": "SCNRF373OPWPB04A5E2B",
"name": "종료시나리오",
"cnt": 1
},
{
"id": "OOS",
"name": null,
"cnt": 8
}
]
},
{
"id": "SCNRF1P2P5NA11352363",
"name": "주문시나리오",
"totalCallCnt": 3,
"recursiveCnt": 1,
"toScenarios": [
{
"id": "OOS",
"name": null,
"cnt": 2
}
]
},
{
"id": "SCNRF31MKPOSAF9F5200",
"name": "123123",
"totalCallCnt": 34,
"recursiveCnt": 10,
"toScenarios": []
},
{
"id": "SCNRF31MN1MO03A8A4EC",
"name": "ddd",
"totalCallCnt": 3,
"recursiveCnt": 0,
"toScenarios": [
{
"id": "OOS",
"name": null,
"cnt": 1
}
]
},
{
"id": "SCNRF373OPWPB04A5E2B",
"name": "종료시나리오",
"totalCallCnt": 1,
"recursiveCnt": 0,
"toScenarios": [
{
"id": "OOS",
"name": null,
"cnt": 1
}
]
},
{
"id": "OOS",
"name": null,
"totalCallCnt": 12,
"recursiveCnt": 0,
"toScenarios": []
}
]
标签必须使用 cnt 属性!
因此链接标签必须显示'1'或'2'或'0'...