D3 中的工具提示如何动态获取数据?

How can a tooltip in D3 fetch data dynamically?

我们有一些数据

University,Total,Females,Males,Year,Type
PortSaid,13817,6679,7138,2012,Public
PortSaid,14790,7527,7263,2013,Public
PortSaid,17295,8509,8786,2010,Public
6OctoberUniversity,12507,4297,8210,2012,Private
6OctoberUniversity,14608,5360,9248,2013,Private

我尝试创建这样的饼图 Block 并附有动态工具提示。 我手动创建了一个 HTML 元素

        <p>
            <strong>University is </strong>
            <span id="UniversityName"></span>
        </p>
        <p><span id="NumberStudents"></span> Students</p>

以及创建圆弧和工具提示的代码

        svg.selectAll("path")
            .data(pie(data))
          .enter().append("path")
            .each(function(d) { d.outerRadius = outerRadius - 20; })
            .attr("d", arc)
            .on("mouseover", arcTween(outerRadius, 0))
            .on("mouseout", arcTween(outerRadius - 20, 150))
            .on("mouseover", function(d) {
                var xPosition = 100;
                var yPosition = 100;
                d3.select("#tooltip")
                    .data(pie(data))
                      .style("left", xPosition + "px")
                      .style("top", yPosition + "px")
                      .select("#NumberStudents")
                        .text(function(d) { return d.value })
                      .select("#UniversityName")
                        .text(function(d) { return d.value });
                    //Show the tooltip
                d3.select("#tooltip").classed("hidden", false);
                })
            .on("mouseout", function() {

                //Hide the tooltip
                d3.select("#tooltip").classed("hidden", true);          
           })

问题: Tooltip 总是 returns Total 列的第一个值,即 13817。它如何根据鼠标悬停弧线动态显示正确的值?


编辑:在代码片段和 HTML 工具提示模板中添加了第二个数据点#UniversityName。

问题 2 正如@minikomi 指出的那样,正确的数据绑定将导致正确获取与每个弧关联的值。然而,似乎每个弧都有一个附加值,正确地标记为 Total。 然而,这会将每行的其余数据留在哪里,如 Female、MaleYear?我怎样才能将它们也绑定到工具提示?

可能值得回顾 d3 和 data binding 到 dom 背后的想法。

这里:

.on("mouseover", function(d) {
            var xPosition = 100;
            var yPosition = 100;
            d3.select("#tooltip")
                .data(pie(data)) // re-bind tooltip with entire data set
                  .style("left", xPosition + "px")
                  .style("top", yPosition + "px")
                  .select("#NumberStudents")
                  .text(function(d) { return d.value });
                //Show the tooltip
            d3.select("#tooltip").classed("hidden", false);
            })

原来data是一个数组。当您使用 .data.enter.each 时,不仅会创建饼图的一部分,而且每个部分还会绑定一个数据点。

因此,当您告诉段对鼠标悬停事件做出反应时,回调函数的 d 参数将由 d3 设置为该段的绑定数据点。

相比之下,在上面的代码中,在选择#tooltip 元素后,会调用 .data(pie(data)) - 这会将 整个数据集 绑定到工具提示每次您将鼠标悬停 - 并且是您观察到的意外行为的原因。

而是使用单个数据项(此处函数中的 d)及其值来设置工具提示的文本:

 .on("mouseover", function(d) {
            // d = the single data point used 
            //     to create the segment here
            var xPosition = 100;
            var yPosition = 100;
            d3.select("#tooltip")
                .style("left", xPosition + "px")
                .style("top", yPosition + "px")
                .select("#NumberStudents")
                  .text(d.value);

            d3.select("#tooltip").classed("hidden", false);
            })

要访问其他值(与用于创建饼图切片的值分开),请检查饼图布局的 docs。原始数据将在 d 的 .data 属性中。因此,例如,假设您的工具提示有一个 #SchoolType <span> 那么您可以从 Type 属性设置文本,例如:

 .on("mouseover", function(d) {

            var xPosition = 100;
            var yPosition = 100;
            d3.select("#tooltip")
                .style("left", xPosition + "px")
                .style("top", yPosition + "px")
                .select("#NumberStudents")
                  .text(d.value)

            //d.data will hold the original data map
            d3.select("#tooltip #SchoolType").text(d.data["Type"]);

            d3.select("#tooltip").classed("hidden", false);
            })