D3 v5强制有向图插值

时间:2019-03-20 09:33:27

标签: javascript jquery d3.js interpolation d3-force-directed

我有一个力向图,其中的节点(圆)在不同的簇中,圆从一个位置移动到另一个位置。这就是我要复制的JLS 12.4.1,是要控制气泡从一个簇移动到另一个簇时的运动

我最初的方法是将过渡设置为tick方法,但是根据收到的建议,经过更多考虑后,我觉得将过渡设置为tick并不是一个好主意,因为它被多次调用。但是,气泡的运动是在刻度函数内部进行控制的,而刻度函数又称为重力函数。我的问题是-在这种情况下是否可以控制气泡路径的移动?

您能告诉我我采用的方法是否正确吗?如果是,在当前代码中我在做什么错?如果没有,您能建议我要去的方向吗?

更新:

我已按照注释从tick函数中删除了代码,并将其包含在我用于动画的timer函数中,代码看起来像这样

var force = d3.forceSimulation(nodes)
    .force('charge', d3.forceManyBody().strength(-300))
    .force('collision', d3.forceCollide().radius(function (d) {
        return 1.1 * d.radius;
    }))
.on('tick', tick);

force.alpha(0.01);
force.alphaDecay = 0.1;
force.alphaTarget(.001);

force.force('x', d3.forceX().x(function (d) {
   return foci[d.state].x;
}));

force.force('y', d3.forceY().y(function (d) {
   return foci[d.state].y;
}));

function tick(e) {
 circle

    .each(gravity(.051 * .8))
    .style("fill", function (d) {
        return d.color;
    })

    .attr("cx", function (d) {
        return d.x;
    })
    .attr("cy", function (d) {
        return d.y;
    })


 }

setTimeout(timer, 10);

function timer() {

    var freezeTimer = 1000;


    d3.range(nodes.length).map(function (i) {
        var currentNode = nodes[i];

        // some business logic to update node object

        console.log(d3.select("#circle_" +currentNode.id));
        d3.select("#circle_" +currentNode.id)
        .transition()
        .attrTween("pathTween", function(d) {
            // console.log(this);
            if(d.previousState == 0 && d.state == 4) {

                var lineData1 = [
                    { x: 840, y: 600 },
                    { x: 800, y: 220 },
                    { x: 120, y: 120 },
                    ];

                    var path = svg.append("path")
                    .attr("d", line(lineData1))
                    .attr("stroke", "red")
                    .attr("fill", "none")
                    .attr("stroke-width", 1)
                    .attr("stroke-linecap", "round")
                    .attr("opacity", "0.5");


                var length = path.node().getTotalLength(); // Get the length of the path
                // console.log("Length: " + length);
                var r = d3.interpolate(0, length); //Set up interpolation from 0 to the path length
                return function(t){
                    var point = path.node().getPointAtLength(r(t)); // Get the next point along the path
                    // console.log(point);
                    circle // Select the circle
                        .attr("x", point.x) // Set the cx
                        .attr("y", point.y)
                        .attr("r", 4) // Set the cy
                }
            } 
        });


    });

0 个答案:

没有答案