D3中的自定义强制定向符号(表为节点)

时间:2016-04-25 12:45:45

标签: javascript d3.js graph

是否可以使用您自己的自定义符号创建强制导向图?我知道你可以制作几个不同的符号(圆形,十字形,菱形,方形,三角形,三角形),但这些符号对我的目的来说都不够复杂。下面是我想要实现的一个例子。基本上我想将节点表示为一个表。

enter image description here

编辑:

作为一个起点,我想使用Force-Directed Graph示例Mike Bostock发布在here上。基本上,我想用表替换圆圈,或者可能是我想要的任何其他自定义形状。

var width = 1000;
var height = 500;
var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height);

d3.json('miserables.json', function(error, graph) {
    if (error) {
        throw error;
    }
    force
        .nodes(graph.nodes)
        .links(graph.links)
        .start();

    var link = svg.selectAll('.link')
        .data(graph.links)
        .enter().append('line')
        .attr('class', 'link')
        .style('stroke-width', function(d) {
            return Math.sqrt(d.value);
        });

    var node = svg.selectAll('.node')
        .data(graph.nodes)
        .enter().append('circle')
        // <--- I should probably append my custom shape here instead of the circle
        .attr('class', 'node')
        .attr('r', 5)
        .style('fill', function (d) {
            return color(d.group);
        })
        .call(force.drag);

    node.append('title')
        .text(function (d) {
            return d.name;
        });

    force.on('tick', function() {
        link.attr('x1', function (d) {
            return d.source.x;
        })
            .attr('y1', function (d) {
                return d.source.y;
            })
            .attr('x2', function (d) {
                return d.target.x;
            })
            .attr('y2', function (d) {
                return d.target.y;
        });

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

编辑2:

经过多次尝试用表替换常规节点后,我仍然没有取得很大进展。虽然我能够创建表并将它们添加到网页,但它们不是图表的一部分。我无法抓住并移动桌子。这是一个有效的Fiddle,下面是代码。

我必须以错误的角度接近这种形式。制作一张桌子似乎最能满足我的需求。制作我自己的SVG元素似乎比它需要的更复杂。

var cols = [
    'Col 1',
    'Col 2'
];

var vals = [
    ['val 1', 'val2'],
    ['val 3', 'val 4']
];

var width = 800;
var height = 500;
var radius = 50;
var color = d3.scale.category20();


//**************************************************//
//*************** Tables as nodes ******************//
//**************************************************//

var arr = [];
var table;

for (var i = 0; i < 5; i += 1) {
    table = d3.select('#canvas').append('table');
    var thead = table.append('thead');
    var tbody = table.append('tbody');
    thead.append('thead')
        .append('tr')
        .selectAll('th')
        .data(cols).enter()
        .append('th')
        .text(function(col) {
            return col;
        });
    var rows = tbody.append('tbody').selectAll('tr')
        .data(vals, function (d) {
            return d;
        })
        .enter()
        .append('tr');
    var cells = rows.selectAll('td')
        .data(function (d) {
            return d;
        })
        .enter().append('td')
        .text(function (d) {
            return d;
        });
    arr.push(table);
}

var force = d3.layout.force()
    .nodes(arr)
    .links([])
    .size(width, height)
    .linkDistance(80)
    .charge(-200)
    .start();

force.on('tick', function() {
    table.style('top', function (d) {
        console.log(d);
        return d;
    });
});


//**************************************************//
//****************** Old graph *********************//
//**************************************************//

var dataset = {
    nodes: [
        {name: "Adam"},
        {name: "Bob"},
        {name: "Carrie"},
        {name: "Donovan"},
        {name: "Edward"},
        {name: "Felicity"},
        {name: "George"},
        {name: "Hannah"},
        {name: "Iris"},
        {name: "Jerry"}
    ],
    edges: [
        {source: 0, target: 1},
        {source: 0, target: 2},
        {source: 0, target: 3},
        {source: 0, target: 4},
        {source: 1, target: 5},
        {source: 2, target: 5},
        {source: 2, target: 5},
        {source: 3, target: 4},
        {source: 5, target: 8},
        {source: 5, target: 9},
        {source: 6, target: 7},
        {source: 7, target: 8},
        {source: 8, target: 9},
        {source: 8, target: 9}
    ]
};


var force2 = d3.layout.force()
    .charge(-3000)
    .linkDistance(200)
    .size([width, height])
    .nodes(dataset.nodes)
    .links(dataset.edges)
    .start()


var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height);

var edges = svg.selectAll('line')
    .data(dataset.edges)
    .enter()
    .append('line')
    .attr('id', function (d, i) {
        return 'edge' + i;
    })
    .style('stroke', '#ccc')
    .style('pointer-events', 'none');

var nodes = svg.selectAll('.node')
    .data(dataset.nodes)
    .enter()
    .append('circle')
    .attr({
        class: 'node'
    })
    .attr('r', radius)
    .style('fill', function (d, i) {
        return color(i);
    })
    .call(force2.drag);

force2.on('tick', function() {
    edges.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;
        }
    });
    nodes.attr({
        'cx': function (d) {
            return d.x = Math.max(radius, Math.min(width - radius, d.x));
        },
        'cy': function (d) {
            return d.y = Math.max(radius, Math.min(height - radius, d.y));
        }
    });
});

1 个答案:

答案 0 :(得分:0)

SVG有一个group元素,您可以使用它来组织可以是任意复杂节点的内容。

此外,您不 使用SVG。你可以用D3来操纵说,HTML表格元素的绝对定位。在您的示例中, print("color: \(color ?? "")") 更新了圆元素的cx和cy属性。它可以轻松更新绝对定位的表元素的顶部和左侧属性。

相关问题