D3。如何在调用功能时更新数据(无按钮)

时间:2017-01-31 13:55:17

标签: javascript d3.js

我有一个带有forceCollide的气泡图。我正在尝试更新数据并在调用功能时更改圆的半径(不带按钮) 此代码正常工作。但是当我使用新数据重新计算功能时,它会重新绘制旧圈子。

function DrawBubbleChart(data) {
        var svg = d3.select("svg")
            ...
        var node = svg.selectAll(".circles")
            ...
        var simulation = d3.forceSimulation(data)
            .force("x", ...)
            .force("y", ...)
            .force("collide", ...);

        simulation.nodes(data)
            .on("tick", ...);   

        d3.select("#btn").on("click", () => {
            node.transition().duration(1000).attr("r", d => d.r);
            simulation.nodes(data);
            simulation.alpha(0.8).restart();
        })
    }  

我正在尝试:

 function DrawBubbleChart(data) {

    if(empty){
            var svg = d3.select("svg")
                ...
            var node = svg.selectAll(".circles")
                ...
            var simulation = d3.forceSimulation(data)
                .force("x", ...)
                .force("y", ...)
                .force("collide", ...);

            simulation.nodes(data)
                .on("tick", ...);   
    } else {
            //d3.select("#btn").on("click", () => {
                node.transition().duration(1000).attr("r", d => d.r);
                simulation.nodes(data);
                simulation.alpha(0.8).restart();
            })
        }  

或类似的东西。这个的最佳方法(解决方案)是什么?

1 个答案:

答案 0 :(得分:1)

创建单个函数来绘制更新气泡图表并不是一个好主意,原因很简单:更新图表时,您必须创建一个具有访问权限的函数到泡沫的先前位置和大小。这些是模拟分配的属性:

  • index - 节点从零开始的节点索引
  • x - 节点的当前x位置
  • y - 节点的当前y位置
  • vx - 节点的当前x速度
  • vy - 节点的当前y速度

而且,在您的情况下,还有一个r。这是可能的,但它很复杂。

我的建议是:创建第一次绘制气泡的函数,然后在该函数内创建另一个处理新数据的函数。这样,过渡是顺利的。

例如,在下面的演示中,我检查气泡数据并更改r属性。您可以创建一个类似的函数,用于更新绑定到气泡的数据,保持其位置。

以下是演示:



var svg = d3.select("svg");

var colour = d3.scaleOrdinal(d3.schemeCategory10);

var data = d3.range(30).map(d => ({
    r: 6
}));

var simulation = d3.forceSimulation(data)
    .force("x", d3.forceX(150).strength(0.05))
    .force("y", d3.forceY(75).strength(0.05))
    .force("collide", d3.forceCollide(function(d) {
        return d.r + 1;
    }));

var node = svg.selectAll(".circles")
    .data(data)
    .enter()
    .append("circle")
    .attr("r", d => d.r)
    .attr("fill", (d, i) => colour(i));

setInterval(()=>{
    d3.selectAll("circle").data().forEach(d => d.r = Math.random()*15);
		node.transition().duration(400).attr("r", d => d.r);
    simulation.nodes(data);
    simulation.alpha(0.8).restart();
}, 3000);

simulation.nodes(data)
    .on("tick", d => {
        node.attr("cx", d => d.x).attr("cy", d => d.y);
    });

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
&#13;
&#13;