d3.forceSimulation
bounding box collision detection. This is useful for label adjustment or rectangular nodes. Each node receives a bounding box array of a top right and bottom left corner of that node relative to its x position. In the case of this dataset, that size is based on the length of the word in the source dataset.
A function for calculating this array based off the data isis passed into the forceRectCollide function, which is later passed as a “collide” constraint in your force settings.
var collide = d3.forceRectCollide(function (d,i) {
var hw = halfWidth(d)
if (i%3 === 0) {
return [[-hw / 2, -hw],[hw / 2, hw]]
}
return [[-hw, -hw / 2],[hw,hw / 2]]
})
.strength(1)
.iterations(2)
The code above creates a vertical or horizontal rectangle. Make sure you make your corresponding on-screen rectangle match the size of your constraint.
<html>
<head>
<title>Bounding Box Collision</title>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="d3-force.js"></script>
</head>
<style>
svg {
height: 1000px;
width: 1000px;
border: 1px solid gray;
}
</style>
<body>
<div id="viz">
<svg class="main">
</svg>
</div>
</body>
<footer>
<script>
d3.csv("words.csv",function(error,data) {createWordcloud(data)});
function createWordcloud(data) {
var networkCenter = d3.forceCenter().x(500).y(500);
var textScale = d3.scaleLinear().domain([10,70]).range([2,30])
var forceX = d3.forceX(function (d) {return 500})
.strength(function (d) {return textScale(d.frequency) * 0.001})
var forceY = d3.forceY(function (d) {return 500})
.strength(function (d) {return textScale(d.frequency) * 0.001})
function halfWidth(d) {
return d.text.length * textScale(d.frequency)
}
var collide = d3.forceRectCollide(function (d,i) {
var hw = halfWidth(d)
if (i%3 === 0) {
return [[-hw / 2, -hw],[hw / 2, hw]]
}
return [[-hw, -hw / 2],[hw,hw / 2]]
})
.strength(1)
.iterations(2)
var color = d3.scaleOrdinal(d3.schemeCategory10)
var force = d3.forceSimulation(data)
.velocityDecay(0.6)
.force("center", networkCenter)
.force("x", forceX)
.force("y", forceY)
.force("collide", collide)
.on("tick", updateNetwork);
var nodeEnter = d3.select("svg.main")
.append("g")
.selectAll("g.node")
.data(data)
.enter()
.append("g")
.attr("class", "node")
nodeEnter.append("rect")
.attr("class", "base")
.style("stroke-width", 1)
.style("stroke", function (d, i) {return d3.color(color(i)).brighter(2)})
.each(function (d,i) {
var hw = halfWidth(d)
if (i%3 === 0) {
d3.select(this)
.style("fill", color(i))
.attr("x", -hw / 2)
.attr("y", -hw)
.attr("height", hw * 2)
.attr("width", hw)
}
else {
d3.select(this)
.style("fill", d3.color(color(i)).darker(2))
.attr("y", -hw / 2)
.attr("x", -hw)
.attr("width", hw * 2)
.attr("height", hw)
}
})
function updateNetwork() {
d3.select("svg.main").selectAll("g.node")
.attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"})
}
}
</script>
</footer>
</html>
text,frequency
layout,43
function,45
data,47
return,34
attr,39
chart,38
array,34
style,34
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,59
we'll,59
zoom,59
append,57
elements,57
layout,33
function,35
layout,33
function,35
data,57
return,33
attr,39
chart,38
array,35
style,35
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,9
we'll,39
zoom,39
append,57
elements,57
layout,33
function,35
layout,63
function,61
data,47
return,36
attr,29
chart,28
array,24
style,24
layouts,22
values,22
need,21
nodes,21
pie,21
use,21
figure,20
circle,19
we'll,19
zoom,19
append,17
elements,17
layout,23
function,21
layout,23
function,21
data,57
return,32
attr,29
chart,28
array,35
style,35
layouts,33
values,33
need,21
nodes,21
pie,21
use,21
figure,20
circle,9
we'll,39
zoom,29
append,17
elements,57
layout,23
function,21
layout,43
function,45
data,47
return,34
attr,39
chart,38
array,34
style,34
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,59
we'll,59
zoom,59
append,57
elements,57
layout,33
function,35
layout,33
function,35
data,57
return,33
attr,39
chart,38
array,35
style,35
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,9
we'll,39
zoom,39
append,57
elements,57
layout,33
function,35
layout,63
function,61
data,47
return,36
attr,29
chart,28
array,24
style,24
layouts,22
values,22
need,21
nodes,21
pie,21
use,21
figure,20
circle,19
we'll,19
zoom,19
append,17
elements,17
layout,23
function,21
layout,23
function,21
data,57
return,32
attr,29
chart,28
array,35
style,35
layouts,33
values,33
need,21
nodes,21
pie,21
use,21
figure,20
circle,9
we'll,39
zoom,29
append,17
elements,57
layout,23
function,21
layout,43
function,45
data,47
return,34
attr,39
chart,38
array,34
style,34
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,59
we'll,59
zoom,59
append,57
elements,57
layout,33
function,35
layout,33
function,35
data,57
return,33
attr,39
chart,38
array,35
style,35
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,9
we'll,39
zoom,39
append,57
elements,57
layout,33
function,35
layout,63
function,61
data,47
return,36
attr,29
chart,28
array,24
style,24
layouts,22
values,22
need,21
nodes,21
pie,21
use,21
figure,20
circle,19
we'll,19
zoom,19
append,17
elements,17
layout,23
function,21
layout,23
function,21
data,57
return,32
attr,29
chart,28
array,35
style,35
layouts,33
values,33
need,21
nodes,21
pie,21
use,21
figure,20
circle,9
we'll,39
zoom,29
append,17
elements,57
layout,23
function,21
layout,43
function,45
data,47
return,34
attr,39
chart,38
array,34
style,34
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,59
we'll,59
zoom,59
append,57
elements,57
layout,33
function,35
layout,33
function,35
data,57
return,33
attr,39
chart,38
array,35
style,35
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,9
we'll,39
zoom,39
append,57
elements,57
layout,33
function,35
layout,63
function,61
data,47
return,36
attr,29
chart,28
array,24
style,24
layouts,22
values,22
need,21
nodes,21
pie,21
use,21
figure,20
circle,19
we'll,19
zoom,19
append,17
elements,17
layout,23
function,21
layout,23
function,21
data,57
return,32
attr,29
chart,28
array,35
style,35
layouts,33
values,33
need,21
nodes,21
pie,21
use,21
figure,20
circle,9
we'll,39
zoom,29
append,17
elements,57
layout,23
function,21
layout,43
function,45
data,47
return,34
attr,39
chart,38
array,34
style,34
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,59
we'll,59
zoom,59
append,57
elements,57
layout,33
function,35
layout,33
function,35
data,57
return,33
attr,39
chart,38
array,35
style,35
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,9
we'll,39
zoom,39
append,57
elements,57
layout,33
function,35
layout,63
function,61
data,47
return,36
attr,29
chart,28
array,24
style,24
layouts,22
values,22
need,21
nodes,21
pie,21
use,21
figure,20
circle,19
we'll,19
zoom,19
append,17
elements,17
layout,23
function,21
layout,23
function,21
data,57
return,32
attr,29
chart,28
array,35
style,35
layouts,33
values,33
need,21
nodes,21
pie,21
use,21
figure,20
circle,9
we'll,39
zoom,29
append,17
elements,57
layout,23
function,21
layout,43
function,45
data,47
return,34
attr,39
chart,38
array,34
style,34
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,59
we'll,59
zoom,59
append,57
elements,57
layout,33
function,35
layout,33
function,35
data,57
return,33
attr,39
chart,38
array,35
style,35
layouts,33
values,33
need,35
nodes,35
pie,35
use,35
figure,30
circle,9
we'll,39
zoom,39
append,57
elements,57
layout,33
function,35
layout,63
function,61
data,47
return,36
attr,29
chart,28
array,24
style,24
layouts,22
values,22
need,21
nodes,21
pie,21
use,21
figure,20