2016-04-11 3 views
1

Я вообще не программист, хотя я пытаюсь написать генератор wordcloud с помощью d3. Я копался в примерах в Интернете, и все работает хорошо до сих пор, но в настоящее время, если я нажму кнопку «Сделать Wordcloud», он просто добавит еще одно словосочетание, и я хочу, чтобы он обновил существующий. Хотя, я считаю, что мне не хватает знаний, чтобы достичь этого. Можете ли вы помочь? Вот код:Нужна помощь по обновлению 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; 
        }); 
      } 
     } 
    } 
}); 

ответ

0

Ключ в вашей функции draw. Обратите внимание на строку d3.select("#drawing").append("svg"). Это означает, что каждый раз, когда функция вызывается, она добавляет еще один SVG. Теперь, когда вы можете создать еще одну функцию для этого, также можно сделать это в рамках одной функции, используя функции, связанные с функцией .data: .enter() и .exit().

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(); 
} 

важные моменты о .data():

  • Эта функция потребляет массив и пытается согласовать этот массив объектов, предусмотренных selectAll("text") отбора (в данном случае).
  • .enter() влияет только на новые объекты, эти элементы в массиве, которые не имеют соответствующий объект (элементы более массивов, чем объекты)
  • И наоборот, .exit() воздействует на объекты, которые не имеют массив соответствия (больше объектов, чем элементы массива)
  • Просто звоните words.<function> будет влиять на все объекты.

Так что это делает создает слова и применяет font-family и text-anchor настройки, а затем обновляет весь текст с их соответствующей font-size, transform и text. Наконец, он удаляет все выходящие слова.

+0

Большое спасибо за ваш ответ! Хотя, я попытался использовать код и не понимаю, почему, но он не обновляет wordcloud. Он больше не создает новый svg, но слова в облаке не обновляются –

Смежные вопросы