2016-04-11 5 views
1

Ich bin überhaupt kein Programmierer, obwohl ich versuche, einen Wordcloud-Generator mit d3 zu schreiben. Ich habe online nach Beispielen gesucht und alles funktioniert soweit, aber wenn ich jetzt auf "Make Wordcloud" klicke, fügt es einfach eine weitere wordcloud hinzu, und ich möchte, dass die vorhandene aktualisiert wird. Allerdings glaube ich, dass mir das Wissen fehlt, um es zu erreichen. Kannst du helfen? Hier ist der Code:Brauchen Sie Hilfe beim Aktualisieren einer D3.js wordcloud

$('#btn-wordcloud').click(function() { 
    if (codebtn_click_counter < 1) { 
     alert("please hit Code Data button first"); 
    } else { 

     // Get all of the words 
     words = []; 
     wordscnt = []; 
     var data = hot.getData(); 
     for (i = 0; i < data.length; i++) { 
      for (j = 1; j < data[i].length; j++) { 
       if (data[i][j]) { 
        if (words[data[i][j]]) { 
         words[data[i][j]]++; 
        } else { 
         words[data[i][j]] = 1; 
        } 
       } 
      } 
     } 

     for (word in words) { 
      if (word != "None" && words[word] > 2) { 
       var row = { 
        "text": word.toUpperCase(), 
        "size": words[word] * 15 
       } 
       wordscnt.push(row) 
      } 
     } 

     if (wordscnt.length > 0) { 
      $('#data').hide(); 
      var fill = d3.scale.category20(); 
      maxSize = d3.max(wordscnt, function(d) { 
       return d.size; 
      }); 
      minSize = d3.min(wordscnt, function(d) { 
       return d.size; 
      }); 

      var fontScale = d3.scale.linear() // scale algo which is used to map the domain to the range 
      .domain([minSize, maxSize]) //set domain which will be mapped to the range values 
      .range([15, 80]); // set min/max font size (so no matter what the size of the highest word it will be set to 40 in this case) 

      if (codebtn_click_counter >= 1 && click_counter == 0) { 
       click_counter = ++click_counter; 
       d3.layout.cloud().size([1000, 500]) 
        .words(wordscnt.sort(sortWordCountObject)) 
       //.rotate(function() { return ~~(Math.random() * 2) * 90; }) 
       .padding(5) 
        .rotate(0) 
        .font("Impact") 
       //.fontSize(function(d) { return d.size; }) 
       .fontSize(function(d) { 
        return fontScale(d.size) 
       }) 
        .on("end", draw) 
        .start(); 
      } else { 
       //* How do I update the svg created? 

      }; 

      function draw(words) { 
       d3.select("#drawing").append("svg") 
        .attr("width", 1000) 
        .attr("height", 500) 
        .append("g") 
        .attr("transform", "translate(500,250)") 
        .selectAll("text") 
        .data(words) 
        .enter().append("text") 
        .style("font-size", function(d) { 
         return d.size + "px"; 
        }) 
        .style("font-family", "Expressway") 
       //* .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; 
        }); 
      } 
     } 
    } 
}); 

Antwort

0

Der Schlüssel liegt in Ihrer draw Funktion. Beachten Sie die Zeile d3.select("#drawing").append("svg"). Dies bedeutet, dass jedes Mal, wenn die Funktion aufgerufen wird, ein weiteres SVG hinzugefügt wird. Nun, während Sie eine andere Funktion erstellen können, ist es auch vollständig möglich, dies innerhalb derselben Funktion zu tun, indem Sie die Funktionen .enter() und .exit() verwenden, die der .data-Funktion zugeordnet sind.

function draw(words) { 
    var words = d3.select("#drawing").selectAll("svg").data([0]).enter().append("svg") 
    .attr("width", 1000) 
    .attr("height", 500) 
    .append("g") 
    .attr("transform", "translate(500,250)") 
    .selectAll("text") 
    .data(words); 

    words.enter().append("text") 
    .style("font-family", "Expressway") 
    //* .style("fill", function(d, i) { return fill(i); }) *// 
    .attr("text-anchor", "middle") 

    words.style("font-size", function(d) { 
     return d.size + "px"; 
    }) 
    .attr("transform", function(d) { 
     return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
    }) 
    .text(function(d) { 
     return d.text; 
    }); 

    words.exit().remove(); 
} 

Die wichtige Punkte über .data(): durch die Auswahl zur Verfügung gestellt (selectAll("text") in diesem Fall)

  • Diese Funktion eine Anordnung verbraucht und versucht, die Objekte, die Anordnung zu passen.
  • .enter() betrifft nur neue Objekte, die Elemente in der Anordnung, die kein passendes Objekt (mehr Array-Elemente als Objekte) hat
  • Umgekehrt .exit() betreffen Gegenstände, die (mehr Objekte als Array-Elemente) nicht einen passenden Array
  • Der Aufruf von wirkt sich auf alle Objekte aus.

Also das, was tut, ist schafft die Worte und wendet die font-family und text-anchor Einstellungen, aktualisiert dann den gesamten Text mit den dazugehörigen font-size, transform und text. Schließlich entfernt es alle ausgehenden Wörter.

+0

Vielen Dank für Ihre Antwort! Obwohl ich versucht habe, den Code zu verwenden, verstehe ich nicht warum, aber die Wordcloud wird nicht aktualisiert. Es wird kein neues Svg mehr erstellt, aber die Wörter in einer Cloud werden nicht aktualisiert –

Verwandte Themen