在D3中的位置内定位节点

时间:2017-01-27 11:04:14

标签: d3.js

如何在SVG元素中定义包含节点的位置? 我正在尝试使用D3创建一个抽象地图,其中节点包含在位置中。然后,节点将链接到其他节点(有时在同一位置+ /或其他位置的许多节点)。

因此样本数据可能如下所示:

{"nodes":[
    {"id": "a", "location": "1"},
    {"id": "b", "location": "1"},
    {"id": "c", "location": "2"},
    {"id": "d", "location": "2"},
    {"id": "e", "location": "3"},
    {"id": "f", "location": "3"},
    {"id": "g", "location": "4"},
    {"id": "h", "location": "4"}]
}

我想创建4个矩形/气泡,每个都有2个节点(圆圈)。 我是D3的新手,我猜我正在努力从简单的数据集转到JSON对象。很抱歉,如果我错过了显而易见的事情。

1 个答案:

答案 0 :(得分:2)

如果您要创建强制定向图表,则可以使用forceXforceY来排列屏幕中的节点。根据{{​​3}}:

  

x和y定位力以可配置的强度将节点推向沿给定尺寸的期望位置。力的强度与节点位置和目标位置之间的一维距离成比例。

在这个演示中,我将根据location获取数据数组并定位在x坐标中。首先,我设定了一个比例:

var xScale = d3.scalePoint()
    .domain([1, 2, 3, 4])
    .range([100, width - 100]);

并在forceX

中使用此比例
var force = d3.forceSimulation(data)
    .force('x', d3.forceX((d) => xScale(d.location)).strength(2))

这是一个演示:

var data = [{
    "id": "a",
    "location": "1"
}, {
    "id": "b",
    "location": "1"
}, {
    "id": "c",
    "location": "2"
}, {
    "id": "d",
    "location": "2"
}, {
    "id": "e",
    "location": "3"
}, {
    "id": "f",
    "location": "3"
}, {
    "id": "g",
    "location": "4"
}, {
    "id": "h",
    "location": "4"
}];

var width = 500,
    height = 200;

var color = d3.scaleOrdinal(d3.schemeCategory10);

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

var xScale = d3.scalePoint()
    .domain([1, 2, 3, 4])
    .range([100, width - 100]);

var circles = svg.selectAll(".bigCircles")
	.data(xScale.domain())
	.enter()
	.append("circle")
	.attr("cx", d=>xScale(d))
	.attr("cy", height/2)
	.attr("fill", d=>color(d))
	.attr("r", 40)
	.attr("opacity", 0.2);

var node = svg.selectAll(".circles")
    .data(data)
    .enter().append("circle")
    .attr("r", 10)
    .attr("fill", (d) => color(d.location));


var force = d3.forceSimulation(data)
    .force('x', d3.forceX((d) => xScale(d.location)).strength(2))
    .force('center', d3.forceCenter(width / 2, height / 2))
    .force("collide", d3.forceCollide(12));

force.nodes(data)
    .on('tick', function() {
        node
            .attr('transform', (d) => {
                return 'translate(' + (d.x) + ',' + (d.y) + ')';
            });
    });
<script src="https://d3js.org/d3.v4.min.js"></script>