【发布时间】:2013-12-02 08:48:20
【问题描述】:
我在地图上放置了与 GPS 坐标相对应的圆圈。每个圆圈都包含在一个 svg 容器中,该容器使用 CSS 顶部和左侧属性放置在页面上。在我的实现中,这些容器经常相互叠放。
我正在尝试实现碰撞检测和/或向这些容器添加轻微的负电荷,以便重叠导致容器彼此远离。
到目前为止,我对强制布局的测试要么没有变化,要么导致错误(“无法设置 null 的属性索引”或“无法设置 null 的属性 x”)。很明显我做错了什么,但我无法从我在网上阅读的文章中找出解决问题的方法。
关于如何阻止容器相互叠放有什么想法吗?
var self = this;
var data = [{lat: 127, lon: 36, name: 'a', radius: 9},{lat:127, lon: 36, name: 'b', radius: 9}];
// Position SVG containers correctly
var latLngToPx = function(d) {
var temp = new google.maps.LatLng(d.lat, d.lon);
temp = self.map.projection.fromLatLngToDivPixel(temp);
d.x = temp.x;
d.y = temp.y;
return d3.select(this)
.style('left', d.x + 'px')
.style('top', d.y + 'px');
};
var collide = function(node) {
var r = node.radius + 16,
nx1 = node.x - r,
nx2 = node.x + r,
ny1 = node.y - r,
ny2 = node.y + r;
return function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== node)) {
var x = node.x - quad.point.x,
y = node.y - quad.point.y,
l = Math.sqrt(x * x + y * y),
r = node.radius + quad.point.radius;
if (l < r) {
l = (l - r) / l * 0.5;
node.x -= x *= l;
node.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
};
}
var svgBind = d3.select(settings[type].layer).selectAll('svg')
.data(data, function(d){ return d.name; })
.each(latLngToPx);
var svg = svgBind.enter().append('svg')
.each(latLngToPx)
// svg[0] contains the svg elements
var nodes = svg[0];
var force = d3.layout.force()
.nodes(nodes)
.charge(-100)
.start();
force.on('tick', function(){
var q = d3.geom.quadtree(nodes),
i = 0,
n = nodes.length;
while (++i < n) {
q.visit(collide(nodes[i]));
}
svg
.style('left', function(d){ return (d.x - lm.config.offset) + 'px';})
.style('top', function(d){ return (d.y - lm.config.offset) + 'px';});
});
var circ = svg.append('circle')
.attr('r', settings[type].r)
.attr('cx',10)
.attr('cy',10)
【问题讨论】:
标签: svg d3.js collision-detection force-layout