Skip to content

Instantly share code, notes, and snippets.

@igez
Last active June 29, 2018 08:35
Show Gist options
  • Save igez/fe5531700db149da7d886666ea267ee9 to your computer and use it in GitHub Desktop.
Save igez/fe5531700db149da7d886666ea267ee9 to your computer and use it in GitHub Desktop.
Shrink group of SVG element and resize its radius & viewport while maintain they relative position
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<svg width='962' height='502'></svg>
<script src='https://d3js.org/d3.v4.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
<script>
var svg = d3.select('svg'),
width = +svg.attr('width'),
height = +svg.attr('height'),
radius = 10;
var padding = radius + 10;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var data = d3.range(10).map(function(range, i) {
var maxW = width * .75;
var minW = width * 0.25;
var maxH = height * .75;
var minH = height * 0.25;
return {
id: range,
x: Math.random() * (maxW - minW) + minW,
y: Math.random() * (maxH - minH) + minH,
radius: 10,
color: color(range)
}
});
var node = svg.selectAll('.node');
var clickable = svg.append('g').on('click', function() {
coverWithArea();
})
clickable
.append('rect')
.attr('x', 10)
.attr('y', 10)
.attr('fill', 'red')
.attr('stroke', 'red')
.attr('width', 100)
.attr('height', 50)
clickable
.append('text')
.attr('fill', 'white')
.attr('x', 60)
.attr('y', 40)
.attr('text-anchor', 'middle')
.text('SHRINK!')
node = node
.data(data)
.enter()
.append('circle')
.attr('class', 'node')
.attr('r', function(d) { return d.radius})
.attr('cx', function(d) { return d.x})
.attr('cy', function(d) { return d.y})
.style('fill', function(d) { return color(d.id); });
var minX = _.minBy(data, function(d) {
return d.x;
}).x;
var minY = _.minBy(data, function(d) {
return d.y;
}).y;
var w = _.maxBy(data, function(d) {
return d.x;
}).x;
var h = _.maxBy(data, function(d) {
return d.y;
}).y;
var dimension = {
width: (w - minX) + (padding * 2),
height: (h - minY) + (padding * 2),
x: minX - padding,
y: minY - padding
}
function coverWithArea() {
var xScale = d3.scaleLinear().domain([minX - padding, w + padding]).range([dimension.x + padding, (dimension.x + 200) - padding])
var yScale = d3.scaleLinear().domain([minY - padding, h + padding]).range([dimension.y + padding, (dimension.y + 200) - padding])
var rScale = d3.scaleLinear().domain([0, 1]).range([0, 10]);
var area = svg
.append('rect')
.attr('width', dimension.width)
.attr('height', dimension.height)
.attr('stroke', 'tomato')
.attr('transform', 'translate('+ dimension.x +','+ dimension.y +')')
.attr('fill', 'none');
area
.transition()
.delay(250)
.duration(1000)
.attr('width', 200)
.attr('height', 200)
.attr('stroke', 'tomato')
.attr('transform', 'translate('+ dimension.x +','+ dimension.y +')')
.attr('fill', 'none');
d3
.selectAll('.node')
.transition()
.delay(250)
.duration(1000)
.attr('cx', function(d) {
console.log(d.x, xScale(d.x))
return xScale(d.x);
})
.attr('cy', function(d) {
console.log(d.x, xScale(d.x))
return yScale(d.y);
})
.attr('r', function(d) {
return rScale( ((minX / w) + (minY / h)) / 2 )
})
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment