D3.js 将不同组的圆节点连接到线强制布局
我已经创建了3组圆,每个圆具有不同的力布局:D3.js 将不同组的圆节点连接到线强制布局,d3.js,force-layout,D3.js,Force Layout,我已经创建了3组圆,每个圆具有不同的力布局: (function () { /****** Functions ******* ************************/ var rand = function (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; /****** Variables ******* *****
(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 + ")";
});
}
})();
}
}())
(函数(){
/******功能*******
************************/
var rand=函数(最小值、最大值){
返回Math.floor(Math.random()*(max-min+1))+min;
};
/******变数*******
************************/
var i,
颜色
宽度=400,
高度=400,
力=[],
coords,
_链接数据,节点数据,
主容器;
/**群坐标**/
坐标=[
[0, 0],
[宽度,0],
[宽度*2,0],
];
颜色=d3.scale.category10();
/******主SVG容器*******
*********************************/
mainContainer=d3。选择(#mainContainer”)。追加(“svg”)
.attr(“宽度”,1165)
.attr(“高度”,650)
.附加(“g”);
对于(i=0;i<3;i++){
forces[i]=d3.layout.force();
(功能(){
/******为一个组生成随机数据*******
*************************************************/
/**具有随机半径的圆的随机数量**/
_nodesData=d3.range(rand(25,45)).map(函数(d,i){
返回{
id:我,
半径:兰特(6,18)
}
});
/**
将子对象添加到半径为0的组中,以获得d3
把它放在中心,把所有其他的圆放在它的轨道上
**/
_nodesData.push({
子项:d3.范围(_nodesData.长度),
半径:0
});
/**添加链接**/
_linksData=d3.layout.tree().links(_nodesData);
/******创建组容器*******
*************************************/
var groupContainer=maincainer.append(“g”)
.attr('类','组')
.attr('id','group'+i)
.attr('transform','translate('+coords[i][0]+','+coords[i][1]+'))
.on('mouseenter',函数(){
var index=d3。选择(this.attr('id')。替换('group','');
//控制台日志(索引);
力[index].alpha(.25);
});
var nodesObjects=groupContainer.selectAll(“.node”);
var linksObjects=groupContainer.selectAll(“.link”)
/******部队布局******/
力[i]。链接距离(函数(){
返回兰特(110130)
})
.充电(功能){
退货-兰特(150200)
})
.重力(0.1+1/兰特(10,50))
.尺寸([宽度、高度])
.on(“滴答”,滴答)
.nodes(_nodesData)
.links(_linksData)
.start();
/******链接******/
//linksObjects=linksObjects.data(_linksData)
//.输入()
//.append(“line”).attr('class','link'))
//
// ;
/******创建节点******/
nodesObjects=nodesObjects.data(_nodesData,函数(d){
返回d.id;
})
.enter().append(“g”)
.attr(“类”、“节点”)
.on('mouseover',函数(){
d3.选择(this).moveToFront();
});
/******创建圆圈******/
nodesObjects.append(“圆”)
.attr(“r”,函数(d){
返回d.radius;
}).样式(“填充”,颜色(i));
函数tick(){
linksObjects.attr({
x1:功能(d){
返回d.source.x;
},
y1:功能(d){
返回d.source.y;
},
x2:功能(d){
返回d.target.x;
},
y2:功能(d){
返回d.target.y;
}
});
属性(“转换”,函数(d){
返回“translate”(“+d.x+”,“+d.y+”);
});
}
})();
}
}())
结果:
问题
有没有办法添加连接圆的线并保持圆在其位置上?
说明:直线应连接到圆,即当圆移动时更新其位置
更新
通过添加线条布局并更新其在勾号事件上的位置来实现,以防止圆圈移动: 您可以调用
force.alpha(0)
在一段时间后停止移动,然后resume()
鼠标输出上的布局。根据你想做什么,这可能对你有用:
如果鼠标移出在超时过期之前发生,您还应清除超时。关于您的问题,以防止圆圈移动: 您可以调用
force.alpha(0)
在一段时间后停止移动,然后resume()
鼠标输出上的布局。根据你想做什么,这可能对你有用:
如果在超时过期之前发生鼠标移出,则还应清除超时。绝对正确。我会给每一行一个类,您可以从唯一标识它的源和目标节点的数据中派生,以便只知道源或目标就可以选择它。然后你需要做的就是在相应的力布局的
tick
handler函数中更新两端的坐标。这正是我刚才所做的,解决了这个问题。非常感谢。我会
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();
});