使用 d3 在现有 div 中更改数据集时替换文本值

Replace text value upon dataset change within an existing div using d3

我试图在选择新数据集时使用 d3.select 替换现有 div 中的文本,但每次选择新数据集时我所写的内容都会添加新的 div。用例是一个排行榜,它挑选出从某个 material(金牌、银牌、铜牌等)中创建对象的顶级人群 (d.Culture)。

有问题的页面:https://3milychu.github.io/whatmakesart/
加载需要整整一分钟(如果您看到条形图,则页面已加载)

我还尝试按照我查看过的其他建议添加 .remove() 和 .exit(),但未成功。

出于某种原因,即使目标 div 是 类,我也必须使用“.myDiv”而不是“#myDiv”来查看文本。

function origins(dataset) {

var totalRows = dataset.length;
console.log(totalRows);

var format = d3.format(".0%");

var origins = d3.nest()
    .key(function(d) { return d.Culture; })
    .rollup(function(v) { return v.length; })
    .entries(dataset)
    .sort(function(a,b) {return d3.descending(a.value,b.value);});
console.log(origins);

 var culture1 = d3.select(".culture").selectAll(".culture1")
    .data(origins)
    .enter()
    .append("div")
    .attr("id", "culture1")
    .filter(function (d, i) { return i === 0;})
    .text(function(d) { return d.key + " " + format(d.value/totalRows); }) 

 <--repeat for "culture2", "culture3", etc. --> 

};

我要定位的 html div:

<!-- Origins -->
<div id ="origins">
    <h1>Origins</h1>
    <div class="culture" id="culture1"></div>
    <div class="culture" id="culture2"></div>
    <div class="culture" id="culture3"></div>
    <div class="culture" id="culture4"></div>
    <div class="culture" id="culture5"></div>
    <div class="culture" id="culture6"></div>
    <div class="culture" id="culture7"></div>
</div>

这里发生了几件有问题的事情。

首先,当您执行 .attr("id", "culture1") 时,您将附加许多具有相同 ID 的 div。这可能会导致各种意外问题。

filter 功能并不像您预期​​的那样有效。当您执行 .filter(function (d, i) { return i === 0;}) 时,您仍在为所有与过滤器不匹配的元素创建空的 div。在 chrome 中使用 DOM 检查器,您会看到大量空的 div。如果您只想从数组中获取第一个元素,我建议只将该数据传递给 data 函数。如果每次将 origins 传递给 data 函数时,origins 的大小都会不同,那么您将需要在退出时删除该元素。但是如果 origins 数组大小相同,则现有数据应该更新。

这应该有助于解决您所看到的行为。可能还有其他问题,但这些都是应该首先解决的明确问题。

我得到以下内容来替换 selection 变化时的行列:

function origins(dataset) {

var totalRows = dataset.length;
console.log(totalRows);

var format = d3.format(".0%");

var origins = d3.nest()
    .key(function(d) { return d.Culture; })
    .rollup(function(v) { return v.length; })
    .entries(dataset)
    .sort(function(a,b) {return d3.descending(a.value,b.value);});
// console.log(origins);

d3.select(".culture").selectAll("text").remove()

var culture1 = d3.select(".culture").selectAll("#ranks")
        .data(origins.filter(function (d, i) { return i === 0;}))
        .enter()
        .append("text")
        .attr("id", "culture1")
        .text(function(d) { return d.key + " " + format(d.value/totalRows); })
        .exit();

<--repeat for all ranks -->
};

将html改为:

    <div id ="origins">
        <h1>Origins</h1>
        <div class="culture" id="ranks"></div>
    </div>

关键是 select div 中的元素类型,并在声明变量和追加之前 .remove() 它们。同样根据 Jeff 的建议,通过 .data() 处的过滤器可以防止创建额外的元素。