使用d3.js创建动态词云

9
我将使用以下示例作为基础,并希望将其制作成动态词云。https://github.com/jasondavies/d3-cloud。数据已添加到数组中,但我的词云未反映出新添加的单词。
<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>

此外,它在第一次刷新时没有添加新单词。请问有人能够纠正或指出我做错了什么吗?谢谢。

你的更新函数没有处理回车选择(其中包含新单词)。 - Lars Kotthoff
谢谢Lars,它有点起作用了,但是添加的单词显示在同一位置,重叠在之前的单词上。对此有什么想法吗? - Aakash Jain
你还需要像之前一样更新现有单词的位置。在调用.data()后将选择保存在一个变量中,然后从中获取输入和更新的选择。 - Lars Kotthoff
1
我尝试在update函数中使用transform属性,但它将d.x定义为未定义的,无法理解此行为,因为相同语法对于draw函数有效。为什么它不能在第二个函数中找到相同数据集中的x,y坐标? - Aakash Jain
谢谢Lars,它解决了我的问题。 - Aakash Jain
显示剩余3条评论
1个回答

9

感谢Larks,我终于完成了这个任务。在这里,我分享代码,希望能帮助其他遇到类似问题的人。

<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>

1
你注意到什么了吗?文字重叠在一起,这意味着布局没有更新。是的,因为它是D3部分,新单词正在添加,但原始云布局没有更新......如果它更新,文本将避免重叠。 - Amit Rana
@Aakash - 我能够获取单词和单词属性,例如 font-"Impact"hasText-true(console.log 输出),但是我该如何渲染/生成必要的 SVG 以将这些呈现到前端?我看到在 broswerify 示例中,您可以将这些附加到元素,但我正在使用 Node JS - user3871

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接