用线连接不同组力布局的圆节点 [英] Connect circle nodes of differect groups force-layouts with lines
问题描述
我以不同的力分布创建了三组圆圈:
(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 + ")";
});
}
})();
}
}())
http://jsfiddle.net/dmitrychuba/h69wqvcy/2/ >
结果:
问题
有没有一种方法可以添加连接圆圈的线并使圆圈保持其位置?
说明:线应连接到圆上,即在圆移动时更新其位置
http://jsfiddle.net/dmitrychuba/h69wqvcy/2/ >
更新
这是通过添加行布局并在刻度事件中更新其位置来实现的
关于防止圈子移动的问题:
您可以在一段时间后调用force.alpha(0)
停止移动,然后在mouseout
上调用resume()
布局.也许这可以为您服务,具体取决于您要执行的操作: http://jsfiddle.net/h69wqvcy/3/
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();
});
如果超时之前发生鼠标超时,您还应该清除超时.
I have created 3 groups of circles each in different force layout:
(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 + ")";
});
}
})();
}
}())
http://jsfiddle.net/dmitrychuba/h69wqvcy/2/
Result:
QUESTION
Is there a way to add lines connecting circles and keep circles on its positions?
Clarification: lines should be connected to circles, i.e. update their positions when circles moves
http://jsfiddle.net/dmitrychuba/h69wqvcy/2/
UPDATE
It was achieved by adding lines layout and updating their positions on tick event
Regarding your question to prevent circles from moving:
You can call force.alpha(0)
to stop the movement after awhile and then resume()
the layout on mouseout
. Maybe this can work for you depending on what you want to do: http://jsfiddle.net/h69wqvcy/3/
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();
});
You should alse clear the timeout if mouseout occurs before the timeout expires.
这篇关于用线连接不同组力布局的圆节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!