Skip to content

Instantly share code, notes, and snippets.

@micahstubbs
Created September 11, 2017 04:41
Show Gist options
  • Save micahstubbs/92e13b8456c072bd04332a62064269a0 to your computer and use it in GitHub Desktop.
Save micahstubbs/92e13b8456c072bd04332a62064269a0 to your computer and use it in GitHub Desktop.
Multiple Shape Drag SVG
license: MIT
border: no

a SVG example that shows how to drag multiple shapes inside of another shape. notice that the red circles can be dragged independently. notice that the black rectangle can also be dragged, keeping it's red-circle children in the same relative positions.

you could also think about this problem as "how to create a hierarchy of draggable shapes?". the short answer is: do it in the dragSubject() function d3-drag docs on drag subjects

an iteration on this very helpful stackoverflow answer, porting it to d3v4 and converts it to es2015 with lebab

this collection of d3-drag experiments also exist in github repo form at micahstubbs/d3-drag-experiments

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.min.js"></script>
<meta charset="utf-8">
<title>d3-drag-experiments</title>
</head>
<body>
<script src="vis.js"></script>
</body>
</html>
const w = 200;
const h = 200;
const drag = d3
.drag()
.on('start', () => {
d3.event.sourceEvent.stopPropagation();
})
.on('drag', function() {
const x = d3.event.x;
const y = d3.event.y;
if (this.tagName == 'circle') {
if (x <= w - 10 && x >= 10 && y <= h - 10 && y >= 10)
d3.select(this).attr('cx', x).attr('cy', y);
} else d3.select(this).attr('transform', `translate(${x},${y})`);
});
const container = d3
.select('body')
.append('svg')
.attr('width', 960)
.attr('height', 500);
const group = container.append('g');
const rect = group
.append('rect')
.attr('width', w)
.attr('height', h)
.attr('x', 10)
.attr('yx', 10);
const circle1 = group
.append('circle')
.attr('cx', 50)
.attr('cy', 50)
.attr('r', 10)
.style('fill', 'red');
const circle2 = group
.append('circle')
.attr('cx', 100)
.attr('cy', 70)
.attr('r', 10)
.style('fill', 'red');
circle1.call(drag);
circle2.call(drag);
group.call(drag);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment