Implemented collisions on nodes

Also included in this is the implementation of stats as html foreign
objects in svgs.
This commit is contained in:
Tom Gallacher 2016-12-06 16:29:45 +00:00
parent 62aef3eec6
commit d82a43d1e3
1 changed files with 86 additions and 43 deletions

View File

@ -66,7 +66,7 @@ var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force('charge', d3.forceManyBody().strength(() => -50).distanceMin(() => 30))
.force('link', d3.forceLink().distance(() => 200).id(function(d) { return d.id; }))
.force('collide', d3.forceCollide().radius(function(d) { return 128 + 0.5; }).iterations(2))
.force('collide', d3.forceCollide().radius(function(d) { return 200 + 0.5; }).iterations(2))
.force('center', d3.forceCenter(width * 1/3, height * 1/3))
function rightRoundedRect(x, y, width, height, radius) {
@ -171,35 +171,26 @@ d3.json('services.json', function(error, graph) {
.attr('stroke-width', '1px')
.attr('fill', '#464646')
// An icon or label that exists within the circle, inside the infobox
stats.append('text')
.attr('class', 'cpu')
.attr('class', 'stat')
.attr('x', '12')
.attr('y', '65')
.attr('text-anchor', 'start')
.attr('fill', 'rgba(255, 255, 255, 0.8)')
.text('CPU: 63%')
var html = stats
.append('switch')
.append('foreignObject')
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
.attr('x', 12)
.attr('y', 57)
.attr('width', 160)
.attr('height', 70)
// From here everything will be rendered with react using a ref.
// However for now these values are hard-coded.
.append('xhtml:div')
.attr('class', 'node_statistics')
// An icon or label that exists within the circle, inside the infobox
stats.append('text')
.attr('class', 'memory')
.attr('class', 'stat')
.attr('x', '12')
.attr('y', '85')
.attr('text-anchor', 'start')
.attr('fill', 'rgba(255, 255, 255, 0.8)')
.text('Memory: 50%')
// An icon or label that exists within the circle, inside the infobox
stats.append('text')
.attr('class', 'network')
.attr('class', 'stat')
.attr('x', '12')
.attr('y', '105')
.attr('text-anchor', 'start')
.attr('fill', 'rgba(255, 255, 255, 0.8)')
.text('Network: 1.23kb/sec')
// Remove with react + dyanmic data.
html.append('p')
.text('CPU: 48%')
html.append('p')
.text('Memory: 54%')
html.append('p')
.text('Network: 1.75kb/sec')
elm.call(d3.drag()
@ -237,7 +228,7 @@ d3.json('services.json', function(error, graph) {
primary.append('path')
.attr('class', 'node')
.attr('d', rect('0', '-39', 170, 78, 2))
.attr('d', rect('0', '-39', 170, 114, 2))
.attr('stroke', '#343434')
.attr('stroke-width', '1px')
.attr('fill', '#464646')
@ -267,11 +258,32 @@ d3.json('services.json', function(error, graph) {
.attr('fill', '#fff')
.text('☇')
var html = primary
.append('switch')
.append('foreignObject')
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
.attr('x', 12)
.attr('y', 87)
.attr('width', 160)
.attr('height', 70)
// From here everything will be rendered with react using a ref.
// However for now these values are hard-coded.
.append('xhtml:div')
.attr('class', 'node_statistics')
// Remove with react + dyanmic data.
html.append('p')
.text('CPU: 48%')
html.append('p')
.text('Memory: 54%')
html.append('p')
.text('Network: 1.75kb/sec')
var secondary = stats.append('g');
secondary.append('path')
.attr('class', 'node')
.attr('d', bottomRoundedRect('0', '-113', 170, 114, 4))
.attr('d', bottomRoundedRect('0', '-149', 170, 114, 4))
.attr('stroke', '#343434')
.attr('stroke-width', '1px')
.attr('fill', '#464646')
@ -279,7 +291,7 @@ d3.json('services.json', function(error, graph) {
secondary.append('text')
.attr('class', 'secondary')
.attr('x', '12')
.attr('y', '150')
.attr('y', '183')
.attr('text-anchor', 'start')
.attr('fill', '#fff')
.text('Secondary')
@ -287,7 +299,7 @@ d3.json('services.json', function(error, graph) {
secondary.append('circle')
.attr('class', 'alert')
.attr('cx', function () { return d3.select(this.parentNode).select('.secondary').node().getBBox().width + 30 })
.attr('cy', '144')
.attr('cy', '177')
.attr('stroke-width', '0px')
.attr('fill', 'rgb(0,175,102)')
.attr('r', '9px')
@ -296,7 +308,7 @@ d3.json('services.json', function(error, graph) {
secondary.append('text')
.attr('class', 'health')
.attr('x', function () { return d3.select(this.parentNode).select('.secondary').node().getBBox().width + 30 })
.attr('y', '149')
.attr('y', '182')
.attr('text-anchor', 'middle')
.attr('fill', '#fff')
.text('❤')
@ -306,9 +318,9 @@ d3.json('services.json', function(error, graph) {
.append('foreignObject')
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
.attr('x', 12)
.attr('y', 160)
.attr('y', 200)
.attr('width', 160)
.attr('height', 100)
.attr('height', 70)
// From here everything will be rendered with react using a ref.
// However for now these values are hard-coded.
.append('xhtml:div')
@ -369,18 +381,49 @@ d3.json('services.json', function(error, graph) {
function ticked() {
// TODO: Remove these values and pull them out of the height of the boxes
// that the constraints belong to.
r=180
r2=130
r=174
r2=270
link
.attr('x1', function(d) { return contrain(width, r, d.source.x) + 80; })
.attr('y1', function(d) { return contrain(height, r2, d.source.y) + 24; })
.attr('x2', function(d) { return contrain(width, r, d.target.x) + 80; })
.attr('y2', function(d) { return contrain(height, r2, d.target.y) + 24; });
.attr('x1', function(d) {
let x;
svg.selectAll('.node_group').each(function (_, i) {
if (i !== d.source.index) return;
x = d3.select(this).node().getBBox().width;
});
return contrain(width, x, d.source.x) + 80;
})
.attr('y1', function(d) {
let y;
svg.selectAll('.node_group').each(function (_, i) {
if (i !== d.source.index) return;
y = d3.select(this).node().getBBox().height;
});
return contrain(height, y, d.source.y) + 24;
})
.attr('x2', function(d) {
let x;
svg.selectAll('.node_group').each(function (_, i) {
if (i !== d.target.index) return;
x = d3.select(this).node().getBBox().width;
});
return contrain(width, x, d.target.x) + 80;
})
.attr('y2', function(d) {
let y;
svg.selectAll('.node_group').each(function (_, i) {
if (i !== d.target.index) return;
y = d3.select(this).node().getBBox().height;
});
return contrain(height, y, d.target.y) + 24;
});
svg.selectAll('.node_group')
.attr('transform', function(d) {
return 'translate(' + contrain(width, r, d.x) + ',' + contrain(height, r2, d.y) + ')';
let x = d3.select(this).node().getBBox().width;
let y = d3.select(this).node().getBBox().height;
return 'translate(' + contrain(width, x, d.x) + ',' + contrain(height, y, d.y) + ')';
});
}
});