Create dynamic Word Cloud using d3.js

19,165

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>
Share:
19,165
Aakash Jain
Author by

Aakash Jain

I work at an MNC in Mohali, India as a Software Developer. I enjoy coding and always up for learning new tricks and technologies to enhance my level. In free time I enjoy strolling over internet, Quora, StackOverflow and 9gags are my favourite destinations.

Updated on July 25, 2022

Comments

  • Aakash Jain
    Aakash Jain almost 2 years

    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