Create dynamic Word Cloud using d3.js

Aakash Jain picture Aakash Jain · Nov 12, 2014 · Viewed 18.7k times · Source

I am using the following example as base and want to make it dynamic word cloud https://github.com/jasondavies/d3-cloud

The data is added to the array but my word-cloud is not reflecting the newly added word(s):

<script>
  var fill = d3.scale.category20();
  var data = [{word:"Hello",weight:20},{word:"World",weight:10},{word:"Normally",weight:25},{word:"You",weight:15},{word:"Want",weight:30},{word:"More",weight:12},{word:"Words",weight:8},{word:"But",weight:18},{word:"Who",weight:22},{word:"Cares",weight:27}];

  d3.layout.cloud().size([500, 500])
          .words(data.map(function(d) {
              return {text: d.word, size: d.weight};
          }))
          .padding(5)
         .rotate(function() { return ~~(Math.random() * 2) * 90; })
         .font("Impact")
         .fontSize(function(d) { return d.size; })
         .on("end", draw)
         .start();

  function draw(words) {
      d3.select("body").append("svg")
           .attr("width", 300)
          .attr("height", 300)
          .append("g")
          .attr("transform", "translate(150,150)")
          .selectAll("text")
          .data(words)
          .enter().append("text")
          .style("font-size", function(d) { return d.size + "px"; })
          .style("font-family", "Impact")
          .style("fill", function(d, i) { return fill(i); })
          .attr("text-anchor", "middle")
          .attr("transform", function(d) {
              return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
          })
         .text(function(d) { return d.text; });
   }

   function drawUpdate(words){
      //alert(JSON.stringify(words));   //shows me the added data

     d3.select("body").selectAll("text")
          .data(words.map(function(d) {
               return {text: d.word, size: d.weight};
          }))
          .style("font-size", function(d) { return d.size + "px"; })
          .style("font-family", "Impact")
          .style("fill", function(d, i) { return fill(i); })
          .attr("text-anchor", "middle")
          .text(function(d) { return d.text; });       
  }

 setInterval(function () { 
    var d_new = data;
    d_new.push({word: "Mappy",weight:35});
     drawUpdate(d_new);
 }, 1500);

</script>

Also, it refreshed the first time, but without the new word added. Could someone please rectify or point out what am I doing wrong in this. Thanks

Answer

Aakash Jain picture Aakash Jain · Nov 12, 2014

Thanks to Larks I was able to get it done. Here I am sharing the code if anyone else faces a similar issue, I hope it can help

<script>

var fill = d3.scale.category20();
  var data = [{word:"Hello",weight:20},{word:"World",weight:10},{word:"Normally",weight:25},{word:"You",weight:15},{word:"Want",weight:30},{word:"More",weight:12},{word:"Words",weight:8},{word:"But",weight:18},{word:"Who",weight:22},{word:"Cares",weight:27}];

d3.layout.cloud().size([500, 500])
      .words(data.map(function(d) {
        return {text: d.word, size: d.weight};
      }))
      .padding(5)
      .rotate(function() { return ~~(Math.random() * 2) * 90; })
      .font("Impact")
      .fontSize(function(d) { return d.size; })
      .on("end", draw)
      .start();

  function draw(words) {
      d3.select("body").append("svg")
        .attr("width", 300)
        .attr("height", 300)
      .append("g")
        .attr("transform", "translate(150,150)")
      .selectAll("text")
        .data(words)
      .enter().append("text")
        .style("font-size", function(d) { return d.size + "px"; })
        .style("font-family", "Impact")
        .style("fill", function(d, i) { return fill(i); })
        .attr("text-anchor", "middle")
        .attr("transform", function(d) {

          return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
        })
        .text(function(d) { return d.text; });
  }
  function drawUpdate(words){
   d3.layout.cloud().size([500, 500])
      .words(words)
      .padding(5)
      .rotate(function() { return ~~(Math.random() * 2) * 90; })
      .font("Impact")
      .fontSize(function(d) { return d.size; })
      .start();


      d3.select("svg")
      .selectAll("g")
        .attr("transform", "translate(150,150)")
      .selectAll("text")
        .data(words).enter().append("text")
        .style("font-size", function(d) { return d.size + "px"; })
        .style("font-family", "Impact")
        .style("fill", function(d, i) { return fill(i); })

        .attr("transform", function(d) {

          return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
        })
        .text(function(d) { return d.text; });



  }

  setInterval(function () { 
        var d_new = data;
        d_new.push({word:randomWord(),weight:randomWeight()});

         drawUpdate(d_new.map(function(d) {
        return {text: d.word, size: d.weight};
      }));
      }, 1500);

  function randomWord() {
          var text = "";
          var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

          for( var i=0; i < 5; i++ )
              text += possible.charAt(Math.floor(Math.random() * possible.length));

          return text;
      }
      function randomWeight(){
        var r = Math.round(Math.random() * 100);
        return r;
      }
</script>