我正在尝试在D3.js中实现有向图。我对d3.forceSimulation()。on('tick')有问题。这是我的源代码:
export class Graph {
g;
svg;
//lines: SimLink[] = [];
//nodes: SimNode[] = [];
constructor(g) {
this.g = g;
this.prepareGraph();
}
prepareGraph() {
this.svg = d3.select('svg');
this.render(this.nodes, this.lines);
}
render(nodes, lines) {
const width = +this.svg.attr('width');
const height = +this.svg.attr('height');
const color = d3.scaleOrdinal(d3.schemeCategory10);
const simulation = d3.forceSimulation(this.nodes)
.force('charge', d3.forceManyBody())
.force('link', d3.forceLink().links(this.lines).id((d: SimNode) => d.id))
.force('center', d3.forceCenter(width / 2, height / 2));
const link = this.g
.attr('class', 'links')
.selectAll('line')
.data(lines)
.enter().append('line')
.attr('stroke-width', d => Math.sqrt(d.value))
.attr('stroke', d => '#D3D3D3');
const node = this.g
.attr('class', 'nodes')
.selectAll('circle')
.data(nodes)
.enter().append('circle')
.attr('r', 2)
.attr('fill', d => color(d.group))
.call(d3.drag()
.on('start', (d) => dragstarted(d))
.on('drag', (d) => dragged(d))
.on('end', (d) => dragended(d)));
node.append('title')
.text(d => d.id);
simulation
.nodes(nodes);
// .on('tick', ticked);
function ticked() {
link
.attr('x1', (d: SimulationLinkDatum<SimulationNodeDatum>) => (d.source as SimulationNodeDatum).x)
.attr('y1', (d: SimulationLinkDatum<SimulationNodeDatum>) => (d.source as SimulationNodeDatum).y)
.attr('x2', (d: SimulationLinkDatum<SimulationNodeDatum>) => (d.target as SimulationNodeDatum).x)
.attr('y2', (d: SimulationLinkDatum<SimulationNodeDatum>) => (d.target as SimulationNodeDatum).y);
node
.attr('cx', (d: SimulationNodeDatum) => d.x)
.attr('cy', (d: SimulationNodeDatum) => d.y);
}
function dragged(d) {
console.log('dragged', d);
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
console.log('dragended', d);
if (!d3.event.active) {
simulation.alphaTarget(0);
}
d.fx = null;
d.fy = null;
}
function dragstarted(d) {
console.log('dragstarted', d);
if (!d3.event.active) {
simulation.alphaTarget(0.3).restart();
}
d.fx = d.x;
d.fy = d.y;
}
}
}
示例数据:
nodes: [
{ id: '1' },
{ id: '2' },
{ id: '3' },
{ id: '4' },
],
lines: [
{ source: '1', target: '2' },
{ source: '2', target: '3' },
{ source: '3', target: '4' },
]
on(“打勾”,打勾)在控制台中引发以下错误:
Error: <line> attribute x1: Expected length, "NaN"
当我注释这行代码时,它只画了我一个点。 为什么链接或节点没有X或Y属性?
有什么想法吗?我在做什么错了?
答案 0 :(得分:-1)
我已经设法解决了我的问题。这是解决方案:
prepareGraph(link, node) {
const g = this.g;
const width = this.g.attr('width');
const height = this.g.attr('height');
const colors = d3.scaleOrdinal(d3.schemeCategory10);
g.append('defs').append('marker')
.append('svg:path')
.attr('d', 'M 0,-5 L 10 ,0 L 0,5')
.attr('fill', '#999')
.style('stroke', 'none');
const simulation = d3.forceSimulation()
.force('link', d3.forceLink().id((d: any) => d.id).distance(100).strength(1))
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width / 2, height / 2));
update(this.links, this.nodes);
function update(links, nodes) {
link = g.selectAll('.link')
.data(links)
.enter()
.append('line')
.attr('class', 'link')
.attr('stroke-width', d => Math.sqrt(d.value))
.attr('stroke', d => '#D3D3D3')
.attr('marker-end', 'url(#arrowhead)');
node = g.selectAll('.node')
.data(nodes)
.enter()
.append('g')
.attr('class', 'node')
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged));
node.append('circle')
.attr('r', 5)
.style('fill', (d, i) => colors(i));
node.append('title').text(d => d.id);
node.append('text').attr('dy', -3).text(d => d.name);
simulation
.nodes(nodes)
.on('tick', ticked);
simulation.force<any>('link')
.links(links);
}