JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://d3js.org/d3.v3.min.js"></script>
<body>
<div class="background">
</div>
</body>
CSS
body {
padding: 0;
margin: 0;
}
.background {
width: 500px;
height: 300px;
border: 1px solid #007aff;
}
.message {
display: inline-block;
font-family: sans-serif;
border-radius: 100vh;
color: white;
padding: 10px;
background-color: #007aff;
position: absolute;
}
.boundary {
display: inline-block;
width: 10px;
height: 10px;
background-color: red;
position: absolute;
}
JavaScript
var background = d3.select('.background');
var width = background.node().getBoundingClientRect().width,
height = background.node().getBoundingClientRect().height;
var nodes = d3.range(50).map(function(d, i) {
return {
text: "Hello"
};
});
var messages = background.selectAll('.message')
.data(nodes)
.enter()
.append('div')
.attr('class', 'message')
.text(d => d.text)
.each(function(d, i) {
d.width = this.getBoundingClientRect().width;
d.height = this.getBoundingClientRect().height;
});
var force = d3.layout.force()
.gravity(0.05)
.charge(-20)
.nodes(nodes)
.size([width, height]);
messages.call(force.drag);
force.on('tick', function(e) {
messages.each(d => {
d.x = Math.max(20, Math.min(width - (d.width+20), d.x));
d.y = Math.max(20, Math.min(height - (d.height+20), d.y));
});
messages.style('left', d => `${d.x}px`)
.style('top', d => `${d.y}px`);
});
force.start();