将数据列添加到工具提示文本

时间:2019-11-06 20:40:20

标签: javascript d3.js

我是D3js的新手。我在堆积的条形图上的工具提示仅显示列值。但是,我也想添加列名。

我按照https://bl.ocks.org/mjfoster83/7c9bdfd714ab2f2e39dd5c09057a55a0中的示例创建了带有工具提示的堆叠式条形图。

HTML部分:

<html>
<head>
<meta charset ="utf-8">
<script src="./js/d3.v5.min.js"></script>
<style>

body {
    margin: auto;
    width: 650px;
    font: 12px arial;
}

</style>
</head>

<body>

<svg id="chart" width="1900" height="900"></svg>

Select type:
<select id="type"></select>

<input type="checkbox" id="sort">
Toggle sort

</body>
</html>

下面是D3js:

d3.csv("./tmp/20191104154746.csv").then(d => chart(d))

function chart(csv) {

    var keys = csv.columns.slice(2);

    var type   = [...new Set(csv.map(d => d.Type))]
    var pmids = [...new Set(csv.map(d => d.PMID))]

    var options = d3.select("#type").selectAll("option")
        .data(type)
    .enter().append("option")
        .text(d => d)

    var svg = d3.select("#chart"),
        margin = {top: 35, left: 35, bottom: 0, right: 0},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom;

    var x = d3.scaleBand()
        .range([margin.left, width - margin.right])
        .padding(0.1)

    var y = d3.scaleLinear()
        .rangeRound([height - margin.bottom, margin.top])

    var xAxis = svg.append("g")
        .attr("transform", `translate(0,${height - margin.bottom})`)
        .attr("class", "x-axis")

    var yAxis = svg.append("g")
        .attr("transform", `translate(${margin.left},0)`)
        .attr("class", "y-axis")

    var z = d3.scaleOrdinal()
        .range(["#000eec","#0016e6","#0036df",])
        .domain(keys);

    update(d3.select("#type").property("value"), 0)

    function update(input, speed) {

        var data = csv.filter(f => f.Type == input)

        data.forEach(function(d) {
            d.total = d3.sum(keys, k => +d[k])
            return d
        })

        y.domain([0, d3.max(data, d => d3.sum(keys, k => +d[k]))]).nice();

        svg.selectAll(".y-axis").transition().duration(speed)
            .call(d3.axisLeft(y).ticks(null, "s"))

        data.sort(d3.select("#sort").property("checked")
            ? (a, b) => b.total - a.total
            : (a, b) => pmids.indexOf(a.PMID) - pmids.indexOf(b.PMID))

        x.domain(data.map(d => d.PMID));

        svg.selectAll(".x-axis").transition().duration(speed)
            .call(d3.axisBottom(x).tickSizeOuter(0))

        var group = svg.selectAll("g.layer")
            .data(d3.stack().keys(keys)(data), d => d.key)

        group.exit().remove()

        group.enter().append("g")
            .classed("layer", true)
            .attr("fill", d => z(d.key));

        var bars = svg.selectAll("g.layer").selectAll("rect")
            .data(d => d, e => e.data.PMID);

        bars.exit().remove()

        bars.enter().append("rect")
            .attr("width", x.bandwidth())
          .on("mouseover", function() { tooltip.style("display", null); })
        .on("mouseout", function() { tooltip.style("display", "none"); })
        .on("mousemove", function(d) {
            var xPosition = d3.mouse(this)[0] - 5;
            var yPosition = d3.mouse(this)[1] - 5;
            tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
            tooltip.select("text").text(d[1]-d[0]);
        })
            .merge(bars)
          .transition().duration(speed)
            .attr("x", d => x(d.data.PMID))
            .attr("y", d => y(d[1]))
            .attr("height", d => y(d[0]) - y(d[1]))

        var text = svg.selectAll(".text")
        .data(data, d => d.PMID);
    }

    var select = d3.select("#type")
        .on("change", function() {
            update(this.value, 800)
        })

    var checkbox = d3.select("#sort")
        .on("click", function() {
            update(select.property("value"), 800)
        })

        // Prep the tooltip bits, initial display is hidden
 var tooltip = svg.append("g")
     .attr("class", "tooltip")
     .style("display", "none");

 tooltip.append("rect")
     .attr("width", 60)
     .attr("height", 20)
     .attr("fill", "white")
     .style("opacity", 0.5);

 tooltip.append("text")
     .attr("x", 30)
     .attr("dy", "1.2em")
     .style("text-anchor", "middle")
     .attr("font-size", "12px")
     .attr("font-weight", "bold");
}


CSV文件:

PMID,Type,Total cholesterol,LDL cholesterol,HDL cholesterol
18617736,Control,5.7,3.9,1.2
18617736,AD,5.7,3.6,1.4
22134919,Control,48.104,0,0
22134919,AD,50.3,0,0
22134919,Control,45.315,0,0
22134919,AD,42.295,0,0
22134919,Control,45.847,0,0
22134919,AD,43.655,0,0
27255810,Control,0,0,0
27255810,AD,0,0,0
27255810,MCI,0,0,0
27255810,Control,0,0,0
27255810,AD,0,0,0
27255810,MCI,0,0,0
12244089,Control 1,0,0,0
12244089,AD 1,0,0,0
12244089,Control 2,0,0,0
12244089,AD 2,0,0,0
12244089,Control 1 Follow up,0,0,0
12244089,AD 1 Follow up,0,0,0

我尝试将d.data.id如下添加到工具提示中,但是它以undef的形式出现:

  .on("mousemove", function(d) {
            var xPosition = d3.mouse(this)[0] - 5;
            var yPosition = d3.mouse(this)[1] - 5;
            tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
            tooltip.select("text").text(d[1]+d.data.id);
        })

1 个答案:

答案 0 :(得分:0)

这是因为d.data.id没有值。数据对象中的键来自CSV文件的标题。在您的CSV文件中,标题为PMIDTypeTotal cholesterolLDL cholesterolHDL cholesterol。如果您想查看PMID,则可能需要尝试d.data.PMID