Another attempt at better bounding box collision for d3 force.
<html>
<head>
<title>d3v4 Simple Word Cloud</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: 500px;
width: 500px;
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)});
//d3.csv("words.csv",function(error,data) {roundWordCloud(data)});
function roundWordCloud(data) {
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX().strength(0.002))
.force("y", d3.forceY().strength(0.002))
.force("collide", d3.forceCollide().radius(function(d) { return 5; })
.iterations(2))
.on("tick", updateNetwork);
var color = d3.scaleOrdinal(d3.schemeCategory10)
var nodeEnter = d3.select("svg.main")
.append("g")
.attr("transform", "translate(250,250)")
.selectAll("g.node")
.data(data)
.enter()
.append("g")
.attr("class", "node")
nodeEnter.append("circle")
.attr("r", 5)
.style("pointer-events", "none")
.style("fill", function (d,i) {return color(i)})
.style("stroke", function (d,i) {return color(i)})
.style("stroke-width", 1)
.style("fill-opacity", 0.2)
function updateNetwork(e) {
d3.select("svg.main").selectAll("g.node")
.attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"});
}
}
function createWordcloud(data) {
var combinedData = [];
combinedData = data
var networkCenter = d3.forceCenter().x(250).y(250);
var textScale = d3.scaleLinear().domain([10,70]).range([2,10])
var forceX = d3.forceX(function (d) {return 250})
.strength(0.02)
var forceY = d3.forceY(function (d) {return 250})
.strength(0.02)
var collide = d3.forceRectCollide(function (d,i) {
return i%2 === 0 ? [[-(d.text.length * textScale(d.frequency)),-15],[(d.text.length * textScale(d.frequency)),15]] : [[-15,-(d.text.length * textScale(d.frequency))],[15,(d.text.length * textScale(d.frequency))]]
})
.strength(1)
.iterations(2)
var color = d3.scaleOrdinal(d3.schemeCategory10)
var force = d3.forceSimulation(combinedData)
.force("center", networkCenter)
.force("x", forceX)
.force("y", forceY)
.force("collide", collide)
.on("tick", updateNetwork);
var nodeEnter = d3.select("svg.main").selectAll("g.node")
.data(combinedData)
.enter()
.append("g")
.attr("class", "node")
nodeEnter.append("rect")
.attr("height", function (d,i) {
return i%2 === 0 ? 30 : d.text.length * textScale(d.frequency) * 2
})
.attr("width", function (d,i) {
return i%2 === 0 ? d.text.length * textScale(d.frequency) * 2 : 30
})
.attr("y", function (d,i) {
return i%2 === 0 ? -15 : -(d.text.length * textScale(d.frequency))
})
.attr("x", function (d,i) {
return i%2 === 0 ? -(d.text.length * textScale(d.frequency)) : -15
})
.style("pointer-events", "none")
.style("fill", function (d,i) {return color(i)})
.style("stroke", function (d,i) {return color(i)})
.style("stroke-width", 1)
.style("fill-opacity", 0.2)
function updateNetwork(e) {
d3.select("svg.main").selectAll("g.node")
.attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"});
}
}
</script>
</footer>
</html>
text,frequency
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