如何用D3js在圆形路径周围绘制大小随机的圆圈,使小圆圈随机分布且不相互重叠。
它应该是这样的:
这是我能得到的
jQuery(document).ready(function () {
var angle, offset, data,
size = [8, 15],
width = 500,
color = d3.scale.category10(),
height = 600,
radius = 200,
dispersion = 10,
svgContainer = d3.select('body').append("svg")
.attr("width", width)
.attr("height", height);
data = d3.range(100).map(function () {
angle = Math.random() * Math.PI * 2;
offset = Math.max(size[0], size[1]) + radius + dispersion;
return {
cx : offset + Math.cos(angle) * radius + rand(-dispersion, dispersion),
cy : offset + Math.sin(angle) * radius + rand(-dispersion, dispersion),
r : rand(size[0], size[1])
};
});
svgContainer.selectAll("circle")
.data(data)
.enter().append("circle")
.attr({
r : function (d) {return d.r},
cx : function (d) {return d.cx},
cy : function (d) {return d.cy},
fill : function (d, i) {return color(i % 3)}
});
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
});
http://jsfiddle.net/yb8bgcrn/1/
更新问题
有没有办法在不使用链接的情况下使用 d3 强制布局显示它?
最佳答案
我已经对您的 fiddle 进行了一些更新,并应用了我在评论中提到的演示中的碰撞检测。希望这会有所帮助。
var angle, offset, data,
size = [8, 15],
width = 500,
color = d3.scale.category10(),
height = 600,
radius = 200,
dispersion = 10,
svgContainer = d3.select('body').append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.gravity(0.05)
.charge(function(d, i) {
return i ? 0 : -2000;
})
.distance(500)
.size([width, height]);
data = d3.range(100).map(function() {
angle = Math.random() * Math.PI * 2;
offset = Math.max(size[0], size[1]) + radius + dispersion;
return {
x: offset + Math.cos(angle) * radius + rand(-dispersion, dispersion),
y: offset + Math.sin(angle) * radius + rand(-dispersion, dispersion),
radius: rand(size[0], size[1])
};
});
force
.nodes(data)
.start();
root = data[0],
color = d3.scale.category10();
root.radius = 0;
root.fixed = true;
root.px = 250; //Center x
root.py = 275; //Center y
var nodes = svgContainer.selectAll("circle")
.data(data)
.enter().append("circle")
.attr({
r: function(d) {
return d.radius
},
cx: function(d) {
return d.x
},
cy: function(d) {
return d.y
},
fill: function(d, i) {
return color(i % 3)
}
});
force.on("tick", function(e) {
var q = d3.geom.quadtree(data),
i = 0,
n = data.length;
while (++i < n) q.visit(collide(data[i]));
svgContainer.selectAll("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
});
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function collide(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 * .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;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
编辑:
你的意思是这样的吗?
var angle, offset, data,
size = [8, 15],
width = 500,
color = d3.scale.category10(),
height = 600,
radius = 200,
dispersion = 10,
svgContainer = d3.select('body').append("svg")
.attr("width", width)
.attr("height", height).append("g");
var force = d3.layout.force()
.gravity(0.05)
.charge(function(d, i) {
return i ? -20 : -2000;
})
.distance(500)
.size([width, height]);
data = d3.range(100).map(function() {
angle = Math.random() * Math.PI * 2;
offset = Math.max(size[0], size[1]) + radius + dispersion;
return {
x: offset + Math.cos(angle) * radius + rand(-dispersion, dispersion),
y: offset + Math.sin(angle) * radius + rand(-dispersion, dispersion),
radius: rand(size[0], size[1])
};
});
force
.nodes(data)
.start();
root = data[0],
color = d3.scale.category10();
root.radius = 0;
root.fixed = true;
root.px = 250; //Center x
root.py = 275; //Center y
var nodes = svgContainer.selectAll("circle")
.data(data)
.enter().append("circle")
.attr({
r: function(d) {
return d.radius
},
cx: function(d) {
return d.x
},
cy: function(d) {
return d.y
},
fill: function(d, i) {
return color(i % 3)
}
});
var rotation = 0;
setInterval(function(){
if(force.alpha()==0){
if(!rotation)
rotation = Math.random() * 50;
else
rotation = rotation+1;
svgContainer.attr("transform","rotate("+rotation+", "+(width/2)+","+(height/2)+")");
}
//force.theta(0.5);
},250);
force.on("tick", function(e) {
var q = d3.geom.quadtree(data),
i = 0,
n = data.length;
while (++i < n) q.visit(collide(data[i]));
svgContainer.selectAll("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
});
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function collide(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 * .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;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
关于javascript - 如何使用 D3js 围绕圆形路径绘制圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33029742/