block by emeeks 4d2d9061818377fc76e910c70345f1c7

Working Rectangular Collide

Full Screen

Seems to be a decent working rectangular collide function for D3’s forceSimulation.

index.html

<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.05)

 var forceY = d3.forceY(function (d) {return 250})
  .strength(0.05)

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>

words.csv

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