需要有关更新D3.js wordcloud的帮助

Need help on updating a D3.js wordcloud

本文关键字:js wordcloud 帮助 D3 更新      更新时间:2024-04-19

虽然我正在尝试使用d3编写一个wordcloud生成器,但我根本不是程序员。我在网上挖掘了一些例子,到目前为止一切都很好,但目前如果我点击"制作Wordcloud"按钮,它只会添加另一个Wordcloud,我希望它更新现有的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;
                    });
            }
        }
    }
});

关键在于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-familytext-anchor设置,然后用它们相关的font-sizetransformtext更新所有文本。最后,它删除了所有退出的单词。