4

我正在制作一个交互式气泡图,并且正在研究将数据分成两组移动到屏幕两侧的功能。我在模拟中使用了定心力,因为我认为它比使用 forceX 和 forceY 提供了更好、更一致的数据显示。但是,我在拆分数据时遇到了麻烦。

我的想法是,由于您可以将匿名函数作为参数传递给 forceX 以确定节点是向左还是向右移动,因此理论上您可以对中心力中的 x 值执行相同的操作。我的中心力代码如下所示:

var forceCenterSplit = d3.forceCenter(function(d) {
            if (d[splitParameter] >= splitVal)
                return 3*width/4;
            else
                return width/4;
        }, height/2)

为了比较,这里是完成同样事情的 forceX 的代码:

var forceXsplit = d3.forceX(function(d) {
                if (d[splitParameter] >= splitVal)
                    return 3*width/4;
                else
                    return width/4;
            }).strength(.05);    

不幸的是,控制台说“Unexpected value NaN parsing cx attribute”。当我运行定心力并将所有数据推送到 cx = 0 (默认值)时。

我在这里缺少一些基本的东西吗?您不能将匿名函数作为参数传递给定心力吗?如果没有,有没有更好的方法来做到这一点?

谢谢!

开始状态

拆分后

// nicer looking splitting forces that use forceCenter
        var forceCenterCombine = d3.forceCenter(width/2, height/2);

        var forceCenterSplit = d3.forceCenter(function(d) {
            if (d[splitParameter] >= splitVal)
                return 3*width/4;
            else
                return width/4;
        }, height/2);

        // simple splitting forces that only use forceX
        var forceXSplit = d3.forceX(function(d) {
            if (d[splitParameter] >= splitVal)
                return 3*width/4;
            else
                return width/4;
        }).strength(.05);

        var forceXCombine = d3.forceX(width/2).strength(.05);

        // collision force to stop the bubbles from hitting each other
        var forceCollide = d3.forceCollide(function(d){
            console.log("forceCollide");
            return radiusScale(d[radiusParam]) + 1;
        }).strength(.75)

        // This code is for the simulation that combines all the forces
        var simulation = d3.forceSimulation()
            .force("center", forceCenterCombine)
            .force("collide", forceCollide)
            .on('end', function(){console.log("Simulation ended!");});

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

var splitFlag = false;

        // dynamically divide the bubbles into two (or probably more later on) groups
        $scope.split = function() {
            // split them apart
            if (!splitFlag){
                console.log("splitForce");
                simulation.force("center", forceXSplit)
                    .force("y", d3.forceY(height/2).strength(.05))
                    .alphaTarget(.25)
                    .restart();
                splitFlag = true;
            }
            // bring them back together
            else {
                console.log("combineForce");
                simulation.force("center", forceCenterCombine)
                    .alphaTarget(.25)
                    .restart();
                splitFlag = false;
            }
        };

在此处输入图像描述

4

1 回答 1

3

不幸的是,答案似乎是否定的。

由于 的本质d3.forceCenter,(“将匿名函数作为参数传递”)是不可能的。API 说:

定心力均匀地平移节点,以使所有节点的平均位置(如果所有节点具有相同的权重,则为质心)位于给定位置 ⟨x,y⟩。(强调我的)

因此,这里没有访问器函数的空间。forceX并且forceY,另一方面...

将坐标访问器设置为指定的数字或函数。(再次强调我的)

...并且可能最适合您。

于 2017-01-25T05:36:35.240 回答