用线连接不同组力布局的圆节点 [英] Connect circle nodes of differect groups force-layouts with lines

查看:92
本文介绍了用线连接不同组力布局的圆节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以不同的力分布创建了三组圆圈:

(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/

更新

这是通过添加行布局并在刻度事件中更新其位置来实现的

解决方案

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

您可以在一段时间后调用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();
                });    

如果超时之前发生鼠标超时,您还应该清除超时.

I have created 3 groups of circles each in different force layout:

(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/

Result:

QUESTION

Is there a way to add lines connecting circles and keep circles on its positions?

Clarification: lines should be connected to circles, i.e. update their positions when circles moves

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

UPDATE

It was achieved by adding lines layout and updating their positions on tick event

解决方案

Regarding your question to prevent circles from moving:

You can call force.alpha(0) to stop the movement after awhile and then resume() the layout on mouseout. Maybe this can work for you depending on what you want to do: 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();
                });    

You should alse clear the timeout if mouseout occurs before the timeout expires.

这篇关于用线连接不同组力布局的圆节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆