block by emeeks 3491c784172b96fe3406ee1a4817d4a6

Slightly Better Colliding

Full Screen

Some improvement in the collision function by basing the collide vector on the depth of overlap. Still some annoying artifacts with the long pieces not getting dragged to the center properly.

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