【问题标题】:Connect circle nodes of differect groups force-layouts with lines用线连接不同组力布局的圆形节点
【发布时间】:2015-11-12 15:44:21
【问题描述】:

我已经创建了 3 组圆圈,每组都有不同的力量布局:

(function () {
    /****** Functions *******
     ************************/
    var rand = function (min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    };

    /****** Variables *******
     ************************/
    var i,
        color,
        width  = 400,
        height = 400,
        forces = [],
        coords,
        _linksData, _nodesData,
        mainContainer;

    /** Coordinates of groups **/
    coords = [
        [0, 0],
        [width, 0],
        [width * 2, 0],
    ];

    color = d3.scale.category10();

    /****** Main SVG container *******
     *********************************/
    mainContainer = d3.select("#main-container").append("svg")
        .attr("width", 1165)
        .attr("height", 650)
        .append("g");

    for (i = 0; i < 3; i++) {
        forces[i] = d3.layout.force();

        (function () {
            /****** Generate Random Data for one Group *******
             *************************************************/

            /** Random amount of circles with random radius **/
            _nodesData = d3.range(rand(25, 45)).map(function (d, i) {
                return {
                    id     : i,
                    radius : rand(6, 18)
                }
            });

            /**
             Add children to group with 0 radius in order to have d3
             position it in center and put all other circles in its orbit
             **/
            _nodesData.push({
                children : d3.range(_nodesData.length),
                radius   : 0
            });

            /** Add links **/
            _linksData = d3.layout.tree().links(_nodesData);


            /****** Create Group Container *******
             *************************************/
            var groupContainer = mainContainer.append("g")
                .attr('class', 'group')
                .attr('id', 'group' + i)
                .attr('transform', 'translate(' + coords[i][0] + ',' + coords[i][1] + ')')
                .on('mouseenter', function () {
                    var index = d3.select(this).attr('id').replace('group', '');
                    // console.log(index);
                    forces[index].alpha(.25);
                });

            var nodesObjects = groupContainer.selectAll(".node");
            var linksObjects = groupContainer.selectAll(".link")

            /****** Force Layout ******/
            forces[i].linkDistance(function () {
                    return rand(110, 130)
                })
                .charge(function () {
                    return -rand(150, 200)
                })
                .gravity(0.1 + 1 / rand(10, 50))
                .size([width, height])
                .on("tick", tick)
                .nodes(_nodesData)
                .links(_linksData)
                .start();

            /****** links ******/
            // linksObjects = linksObjects.data(_linksData)
            //     .enter()
            //     .append("line").attr('class', 'link')
            //
            // ;

            /****** Create nodes ******/
            nodesObjects = nodesObjects.data(_nodesData, function (d) {
                    return d.id;
                })
                .enter().append("g")
                .attr("class", "node")
                .on('mouseover', function () {
                    d3.select(this).moveToFront();
                });


            /****** Create circles ******/
            nodesObjects.append("circle")
                .attr("r", function (d) {
                    return d.radius;
                }).style("fill", color(i));


            function tick() {
                linksObjects.attr({
                    x1 : function (d) {
                        return d.source.x;
                    },
                    y1 : function (d) {
                        return d.source.y;
                    },
                    x2 : function (d) {
                        return d.target.x;
                    },
                    y2 : function (d) {
                        return d.target.y;
                    }
                });

                nodesObjects.attr("transform", function (d) {
                    return "translate(" + d.x + "," + d.y + ")";
                });
            }

        })();
    }
}())

http://jsfiddle.net/dmitrychuba/h69wqvcy/2/

结果:

问题

有没有办法添加连接圆圈的线并将圆圈保持在其位置上?

澄清:线应该连接到圆圈,即当圆圈移动时更新它们的位置

http://jsfiddle.net/dmitrychuba/h69wqvcy/2/

更新

这是通过添加线条布局并在滴答事件上更新它们的位置来实现的

【问题讨论】:

  • 当然。我会给每一行一个类,您可以从源节点和目标节点的数据中派生出一个类,该类唯一地标识它,以便仅知道源或目标就可以选择它。然后你需要做的就是在各自的力布局的tick处理函数中更新两端的坐标。
  • 这正是我刚刚所做的,它解决了这个问题。谢谢

标签: d3.js force-layout


【解决方案1】:

关于防止圈子移动的问题:

您可以在一段时间后调用force.alpha(0) 停止移动,然后在mouseout 上调用resume() 布局。也许这对你有用,具体取决于你想做什么:http://jsfiddle.net/h69wqvcy/3/

            var groupContainer = mainContainer.append("g")
                .attr('class', 'group')
                .attr('id', 'group' + i)
                .attr('transform',
                'translate(' + coords[i][0] + ',' + coords[i][1] + ')')
                .on('mouseenter', function () {
                    var index = d3.select(this).attr('id').replace('group', '');
                    // console.log(index);
                    forces[index].alpha(0.25);
                    setTimeout(function () {
                        forces[index].alpha(0);
                    }, 1000);
                })
                .on('mouseout', function () {
                    var index = d3.select(this).attr('id').replace('group', '');
                    // console.log(index);
                    forces[index].resume();
                });    

如果在超时到期之前发生 mouseout,您还应该清除超时。

【讨论】:

  • 我不认为这是问题 - OP 正在询问如何在圆圈移动时更新线条的位置。
  • 也许我误解了这个问题。如果OP再次澄清问题,那就太好了。
猜你喜欢
  • 2014-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多