Dynamic Border Around Shapes
http://stackoverflow.com/questions/25086712/d3-create-dynamic-border-rectangle-around-svg-group
by Nivaldo
HTML
<h5>→ check commented out code; author says is an improvement?</h5>
<div>Click the button to add a circle.</div>
<div>Click a circle to remove it.</div>
CSS
svg {
border: 1px solid #ccc;
}
.bounding-rect {
stroke: red;
stroke-width: 2;
fill: transparent;
}
.dot {
fill: steelblue;
}
JavaScript
var w = 400,
h = 300,
margin = 50;
var addBtn = d3.select('body').append('div').append('button')
.text('Add Circle')
.on('click', function() {addCircles(1);});
// CREATE THE SVG
var svg = d3.select('body').append('svg')
.attr('width', w + 2*margin)
.attr('height', h + 2*margin)
.append('g')
.attr('transform', 'translate(' + margin + ',' + margin + ')');
// CREATE THE GROUP
var theGroup = svg.append('g')
.attr('class', 'the-group');
// CREATE ITS BOUNDING RECT
var theRect = theGroup.append('rect')
.attr('class', 'bounding-rect');
// INITIALIZE WITH A FEW CIRCLES
addCircles(4);
updateRect();
function updateRect() {
// SELECT ALL CHILD NODES EXCEPT THE BOUNDING RECT
var allChildNodes = theGroup.selectAll(':not(.bounding-rect)')[0]
// `x` AND `y` ARE SIMPLY THE MIN VALUES OF ALL CHILD BBOXES
var x = d3.min(allChildNodes, function(d) {return d.getBBox().x;}),
y = d3.min(allChildNodes, function(d) {return d.getBBox().y;}),
// WIDTH AND HEIGHT REQUIRE A BIT OF CALCULATION
width = d3.max(allChildNodes, function(d) {
var bb = d.getBBox();
return (bb.x + bb.width) - x;
}),
height = d3.max(allChildNodes, function(d) {
var bb = d.getBBox();
return (bb.y + bb.height) - y;
});
// UPDATE THE ATTRS FOR THE RECT
theRect.transition().duration(1000)
.attr('x', x)
.attr('y', y)
.attr('width', width)
.attr('height', height);
}
function addCircles(n) {
for (var i = 0; i < n; i++) {
theGroup.append('circle')
.attr('class', 'dot')
.attr('cx', Math.random() * w)
.attr('cy', Math.random() * h)
.attr('r', Math.random() * 20 + 4)
.on('click', function() {
d3.select(this).remove();
updateRect();
});
}
updateRect();
}
/*
var w = 400,
h = 300,
margin = 50;
var addBtn = d3.select('body').append('div').append('button')
.text('Add Circle')
.on('click', function()...