为了在节点上渲染标签,我尝试了如下各种方法:
var labels = node.append("text")
.text(function (d) { return d.label; })
.attr('x', 6)
.attr('y', 3);
node.append("title")
.text(function (d) { return d.label; });
或者类似这样的:
node.append("text")
// .attr("text-anchor", "middle")
// .attr("alignment-baseline", "middle")
.text(d => d.label)
.attr('x', 6)
.attr('y', 3);
这是我的完整代码:
<svg id="chart">
</svg>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
let drag = simulation => {
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart()
event.subject.fx = event.subject.x
event.subject.fy = event.subject.y
}
function dragged(event) {
event.subject.fx = event.x
event.subject.fy = event.y
}
function dragended(event) {
if (!event.active) simulation.alphaTarget(0)
event.subject.fx = null;
event.subject.fy = null;
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
}
let height = 600
let width = 600
let data = {
"nodes": [{
"id": "Myriel",
"label": "Myriel name"
},
{
"id": "Napoleon",
"label": "Napoleon name"
}
],
"links": [{
"source": "Myriel",
"target": "Napoleon",
"label": "hit me baby one more time"
},
{
"source": "Napoleon",
"target": "Myriel",
"label": "meaw"
}
]
}
const links = data.links.map(d => Object.create(d))
const nodes = data.nodes.map(d => Object.create(d))
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
const svg = d3.select("#chart")
.attr("viewBox", [0, 0, width, height])
// Define the arrowhead marker
svg.append("defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
// Add the links with arrowheads
const link = svg.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(links)
.join("line")
.attr("stroke-width", 1)
.attr("marker-end", "url(#end)"); // Add the marker-end attribute to link
link.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.text(d => d.label);
const node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", 5)
.attr("fill", () => "#" + Math.floor(Math.random() * 16777215).toString(16))
.call(drag(simulation))
// node.append("text")
// // .attr("text-anchor", "middle")
// // .attr("alignment-baseline", "middle")
// .text(d => d.label)
// .attr('x', 6)
// .attr('y', 3);
var labels = node.append("text")
.text(function (d) { return d.label; })
.attr('x', 6)
.attr('y', 3);
node.append("title")
.text(function (d) { return d.label; });
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
node
.attr("cx", d => d.x)
.attr("cy", d => d.y)
})
</script>
我该怎么做?
虽然在dom下可以使用,但是不可见。我已经尝试设置他们的位置很长一段时间了。
正如评论中提到的,将
text
元素作为 circle
的子元素是无效的 SVG。相反,将节点更改为 g
,然后将圆圈和文本放在其中。
这是对您的代码的快速更改:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="lib/style.css" />
<script src="lib/script.js"></script>
</head>
<body>
<svg id="chart"></svg>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
let drag = (simulation) => {
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
return d3
.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended);
};
let height = 100;
let width = 100;
let data = {
nodes: [
{
id: 'Myriel',
label: 'Myriel name',
},
{
id: 'Napoleon',
label: 'Napoleon name',
},
],
links: [
{
source: 'Myriel',
target: 'Napoleon',
label: 'hit me baby one more time',
},
{
source: 'Napoleon',
target: 'Myriel',
label: 'meaw',
},
],
};
const links = data.links.map((d) => Object.create(d));
const nodes = data.nodes.map((d) => Object.create(d));
const simulation = d3
.forceSimulation(nodes)
.force(
'link',
d3.forceLink(links).id((d) => d.id)
)
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width / 2, height / 2));
const svg = d3.select('#chart').attr('viewBox', [0, 0, width, height]);
// Define the arrowhead marker
svg
.append('defs')
.selectAll('marker')
.data(['end']) // Different link/path types can be defined here
.enter()
.append('svg:marker') // This section adds in the arrows
.attr('id', String)
.attr('viewBox', '0 -5 10 10')
.attr('refX', 15)
.attr('refY', -1.5)
.attr('markerWidth', 6)
.attr('markerHeight', 6)
.attr('orient', 'auto')
.append('svg:path')
.attr('d', 'M0,-5L10,0L0,5');
// Add the links with arrowheads
const link = svg
.append('g')
.attr('stroke', '#999')
.attr('stroke-opacity', 0.6)
.selectAll('line')
.data(links)
.join('line')
.attr('stroke-width', 1)
.attr('marker-end', 'url(#end)'); // Add the marker-end attribute to link
link
.append('text')
.attr('text-anchor', 'middle')
.attr('alignment-baseline', 'middle')
.text((d) => d.label);
const node = svg
.append('g')
.attr('stroke', '#fff')
.attr('stroke-width', 1.5)
.selectAll('g')
.data(nodes)
.join('g');
node
.append('circle')
.attr('r', 5)
.attr(
'fill',
() => '#' + Math.floor(Math.random() * 16777215).toString(16)
)
.call(drag(simulation));
// node.append("text")
// // .attr("text-anchor", "middle")
// // .attr("alignment-baseline", "middle")
// .text(d => d.label)
// .attr('x', 6)
// .attr('y', 3);
var labels = node
.append('text')
.text(function (d) {
return d.label;
})
.attr('x', 6)
.attr('y', 3)
.attr('stroke', 'black')
.style('font-family', 'sans-serif')
.style('font-size', '10px');
node.append('title').text(function (d) {
return d.label;
});
simulation.on('tick', () => {
link
.attr('x1', (d) => d.source.x)
.attr('y1', (d) => d.source.y)
.attr('x2', (d) => d.target.x)
.attr('y2', (d) => d.target.y);
node
.select('circle')
.attr('cx', (d) => d.x)
.attr('cy', (d) => d.y);
node
.select('text')
.attr('x', (d) => d.x)
.attr('y', (d) => d.y);
});
</script>
</body>
</html>