【问题标题】:Updating D3 bubble radius with collide simulation使用碰撞模拟更新 D3 气泡半径
【发布时间】:2017-11-03 06:49:47
【问题描述】:

我一直在努力使用 D3 尝试使用实时更新气泡大小的强制碰撞来制作一个简单的气泡图。

我可以在强制碰撞的第一次数据更新时显示图表。然而,随后的数据调用会冻结图表,并且尺寸永远不会更新:

https://jsfiddle.net/d2zcfjfa/1/

node = svg.selectAll('g.node')
    .data(root.children)
    .enter()
    .append('g')
    .attr('class', 'node')
    .append('circle')
    .attr('r', function(d) { return d.r * 1.4; })
    .attr('fill', function(d) { return color(d.data.name); })
    .call(d3.drag()
        .on("start", dragStart)
        .on("drag", dragged)
        .on("end", dragEnd));

var circleUpdate = node.select('circle')
    .attr('r', function(d)
    {
        return d.r;
    });

simulation.nodes(root.children);

我可以让更新工作,但只能不使用此处所示的碰撞模拟:

https://jsfiddle.net/rgdox7g7/1/

node = svg.selectAll('g.node')
    .data(root.children)
    .enter()
    .append('g')
    .attr('id', function(d) { return d.id; })
    .attr('class', 'node')
    .attr('transform', function(d)
    {
        return "translate(" + d.x + "," + d.y + ")";
    });

var nodeUpdate = svg.selectAll('g.node')
    .transition()
    .duration(2000)
    .ease(d3.easeLinear);

var circleUpdate = nodeUpdate.select('circle')
    .attr('r', function(d)
    {
        return d.r;
    });

node.append("circle")
    .attr("r", function(d) { return d.r; })
    .style('fill', function(d) { return color(d.data.name); });

我尝试将这两种解决方案混合在一起的所有方法都不起作用。我已经在互联网上搜索了其他示例,但我找不到任何帮助。有人可以帮我理解该怎么做吗?我从没想过D3会如此令人沮丧!

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    stackoverflow:您必须回答自己的问题的地方。

    这是我的工作解决方案: https://jsfiddle.net/zc0fgh6y/

    var subscription = null;
    var width = 600;
    var height = 300;
    var maxSpeed = 1000000;
    var pack = d3.pack().size([width, height]).padding(0);
    var svg = d3.select('svg');
    var node = svg.selectAll("g.node");
    var root;
    var nodes = [];
    var first = true;
    var scaleFactor = 1.4;
    
    var color = d3.interpolateHcl("#0faac3", "#dd2323");
    
    var forceCollide = d3.forceCollide()
        .strength(.8)
        .radius(function(d)
        {
            return d.r;
        }).iterations(10);
    
    var simulationStart = d3.forceSimulation()
        .force("forceX", d3.forceX(width/2).strength(.04))
        .force("forceY", d3.forceY(height/2).strength(.2))
        .force('collide', forceCollide)
        .on('tick', ticked);
    
    var simulation = d3.forceSimulation()
        .force("forceX", d3.forceX(width/2).strength(.0005))
        .force("forceY", d3.forceY(height/2).strength(.0025))
        .force('collide', forceCollide)
        .on('tick', ticked);
    
    function ticked()
    {
        if (node)
        {
            node.attr('transform', function(d)
            {
                return "translate(" + d.x + "," + d.y + ")";
            }).select('circle').attr('r', function(d)
            {
                return d.r;
            });
        }
    }
    
    function rand(min, max)
    {
        return Math.random() * (max - min) + min;
    };
    
    
    setInterval(function()
    {
        var hosts = [];
        for (var i = 0; i < 100; i++)
        {
            hosts.push({name: i, cpu: rand(10,100), speed: rand(0,maxSpeed)});
        }
    
        root = d3.hierarchy({children: hosts})
            .sum(function(d)
            {
                return d.cpu ? d.cpu : 0;
            });
    
        var leaves = pack(root).leaves().map(function(item)
        {
            return {
                id: 'node-'+item.data.name,
                name: item.data.name,
                r: item.r * scaleFactor,
                x: width/2,
                y: height/2,
                cpu: item.data.cpu,
                speed: item.data.speed
            };
        });
    
        for (var i = 0; i < leaves.length; i++)
        {
            if (nodes[i] && nodes[i].id == leaves[i].id)
            {
                var oldR = nodes[i].newR;
                nodes[i].oldR = oldR;
                nodes[i].newR = leaves[i].r;
                nodes[i].cpu = leaves[i].cpu;
                nodes[i].speed = leaves[i].speed;
            }
            else
            {
                nodes[i] = leaves[i];
                //nodes[i].r = 1;
                nodes[i].oldR = 1;//nodes[i].r;
                nodes[i].newR = leaves[i].r;
            }
        }
    
        if (first)
        {
            first = false;
    
            node = node.data(nodes, function(d) { return d.id; });
    
            node = node.enter()
                .append('g')
                .attr('class', 'node');
    
            node.append("circle")
                .style("fill", 'transparent');
    
            node.append("text")
                .attr("dy", "0.3em")
                .style('fill', 'transparent')
                .style("text-anchor", "middle")
                .text(function(d)
                {
                    return d.name;//.substring(0, d.r / 4);
                });
    
            // transition in size
            node.transition()
                .ease(d3.easePolyInOut)
                .duration(950)
                .tween('radius', function(d)
                {
                    var that = d3.select(this);
                    var i = d3.interpolate(1, d.newR);
                    return function(t)
                    {
                        d.r = i(t);
                        that.attr('r', function(d)
                        {
                            return d.r;
                        });
                        simulationStart.nodes(nodes).alpha(1);
                    }
                });
    
            // fade in text color
            node.select('text')
                .transition()
                .ease(d3.easePolyInOut)
                .duration(950)
                .style('fill', 'white');
    
            // fade in circle size
            node.select('circle')
                .transition()
                .ease(d3.easePolyInOut)
                .duration(950)
                .style('fill', function(d)
                {
                    return color(d.speed / maxSpeed);
                });
        }
        else
        {
            // transition to new size
            node.transition()
                .ease(d3.easeLinear)
                .duration(950)
                .tween('radius', function(d)
                {
                    var that = d3.select(this);
                    var i = d3.interpolate(d.oldR, d.newR);
                    return function(t)
                    {
                        d.r = i(t);
                        that.attr('r', function(d)
                        {
                            return d.r;
                        });
                        simulation.nodes(nodes).alpha(1);
                    }
                });
    
            // transition to new color
            node.select('circle')
                .transition()
                .ease(d3.easeLinear)
                .duration(950)
                .style('fill', function(d)
                {
                    return color(d.speed / maxSpeed);
                });
        }
    }, 1000);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-30
      • 1970-01-01
      • 1970-01-01
      • 2015-07-11
      • 2021-04-09
      相关资源
      最近更新 更多