D3.js力导向模拟新增节点出现NaN坐标问题求助
解决D3.js力导向图新增节点出现NaN坐标的问题
嘿,作为刚上手D3.js的新手,碰到这个问题太正常了!我来帮你捋清楚问题出在哪,以及怎么修复。
问题根源
你现在的代码只做到了新增节点到数组并更新DOM,但没有把新节点同步到力导向模拟里!D3的forceSimulation不会自动监听你的nodes数组变化——初始调用simulation.nodes(nodes)只是把当时的两个节点传给模拟,后来新增的第三个节点完全没被模拟“认”到,自然没有初始化x、y这些位置属性,就出现了NaN。
修复方案
只需要在新增节点后,手动把更新后的节点数组传给模拟,然后重启模拟让它重新计算布局就行。具体修改如下:
const svg = d3.select('svg'); const height = +svg.attr('height'); const width = +svg.attr('width'); // Test Data const nodes = [ {}, {} ]; setTimeout(() => { nodes.push({}); redraw(); // 关键新增:更新模拟节点并重启,alpha(0.3)让模拟重新活跃起来 simulation.nodes(nodes).alpha(0.3).restart(); }, 2000); const ticked = () => { svg.selectAll('g.node') .attr('transform', d => { if (isNaN(d.x) || isNaN(d.y)) { console.error('nan!!!'); d.x = 50; d.y = 50; } return `translate(${d.x},${d.y})`; }); }; const simulation = d3.forceSimulation() .force('repulsion', d3.forceManyBody().strength(-30)) .force('pin_y_to_center', d3.forceY().y(d => height / 2).strength(0.1)) .force('pin_x_to_center', d3.forceX().x(d => width / 2).strength(0.1)); simulation.nodes(nodes); simulation.on('tick', ticked); const redraw = () => { const node = svg .selectAll('.node') .data(nodes) .enter().append('g'); node.attr('class', 'node') .append('circle') .attr('r', 5); }; redraw();
关键修改说明
simulation.nodes(nodes):把更新后的节点数组传给模拟,让它“感知”到新节点的存在.alpha(0.3):模拟运行一段时间后alpha值会降到0(冷却状态),设置非零值可以唤醒模拟,重新开始布局计算.restart():重启模拟,让它遍历所有节点(包括新节点),初始化位置并应用力导向规则
这样修改后,第三个节点就能被正确分配坐标,不会再出现NaN的问题啦!
内容的提问来源于stack exchange,提问作者Alon
相关产品推荐
相关产品推荐

