首页 > 解决方案 > How to place text inside each bar of the chart using d3

问题描述

I am trying to insert some text inside each bar of the given chart with it's values and I just can't figure it out. I'm still new to d3 and struggle with most of the things.

I also need to have different text inside each bar, dependent on the data.

I've looked up around and found that I need to use the following structure:

<g class="barGroup">
   <rect />
   <text />
</g>

This is how the chart looks: Chart image

This is how I want to achieve: Goal

This is the function which creates the whole chart, the part where I attempt to insert the text is at the end:

function createBarChart(divChartId, receivedData, chartDimensions) {
    // Set dimensions
    var margin = chartDimensions["margin"];
    var width = chartDimensions["width"];
    var height = chartDimensions["height"];

    // Create Svg and group
    var svg = d3.select(divChartId)
        .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // Create and append X axis
    var xAxis = d3.scaleBand()
        .range([0, width])
        .domain(receivedData.map(function (d) { return d.answerText; }))
        .padding(0.2);
    svg.append("g")
        .attr("class", "x-axis")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(xAxis))
        .selectAll("text")
        .attr("class", "font-weight-bold")
            .attr("transform", "translate(-10,0)rotate(-45)")
            .style("text-anchor", "end")
        .style("font-size", "1rem");

    // Create and append Y axis
    var yAxis = d3.scaleLinear()
        .domain([0, Math.max.apply(Math, receivedData.map(function (d) { return d.answerCount; }))])
        .range([height, 0]);
    svg.append("g")
        .attr("class", "y-axis")
        .call(d3.axisLeft(yAxis)
            .ticks(5)
            .tickFormat(d3.format("d")));

    // create a tooltip
    var tooltip = d3.select("body")
        .append("div")
        .attr("class", "font-weight-bold text-dark px-2 py-2")
        .style("position", "absolute")
        .style("z-index", "10")
        .style("visibility", "hidden")
        .style("background", "lavender")
        .style("border", "1px solid gray")
        .style("border-radius", "12px")
        .style("text-align", "center")
        .style("visibility", "hidden")
        .style("visibility", "hidden")
        .style("visibility", "hidden")

    // Generate random color
    var colorObject = generateRandomColorObject();

    // Create and append bars, set values to 0 for animation start
    svg.selectAll("rect").data(receivedData)
        .enter()
            .append("g")
            .attr("class", "barGroup")
                .append("rect")
                .attr("x", function (d) { return xAxis(d.answerText); })
                .attr("y", function (d) { return yAxis(0); })
                .attr("width", xAxis.bandwidth())
                .attr("height", function (d) { return height - yAxis(0); })
                .attr("fill", colorObject.color)
                .style("stroke", colorObject.border)
                .style("stroke-width", 1)
                .on("mouseover", function (d) { return tooltip.style("visibility", "visible").html(d.answerText + ": " + d.answerCount); })
                .on("mousemove", function () { return tooltip.style("top", (event.pageY - 45) + "px").style("left", (event.pageX) + 5 + "px"); })
                .on("mouseout", function (d) { return tooltip.style("visibility", "hidden").html(""); });

    // Set correct values for animation end
    svg.selectAll("rect")
        .transition().duration(1500)
        .attr("y", function (d) { return yAxis(d.answerCount); })
        .attr("height", function (d) { return height - yAxis(d.answerCount); })
        .delay(function (d, i) { return (i * 100) }); 

    // Append text to each bar
    svg.selectAll("barGroup")
        .append("text")
        .attr("font-size", "2em")
        .attr("color", "black")
        .text("Test");
}

标签: javascriptd3.js

解决方案


在这一行中,您希望选择器查找一个类:svg.selectAll("barGroup")应该是svg.selectAll(".barGroup"). 然后,一旦你看到你的文本出现,你就需要定位它们。

考虑将你g.barGroups的第一个,使用.attr('transform', function(d){ return 'translate(...)' },在你.append('rect').append('text')。这样,整个组将处于大致正确的位置,您可以对rect和进行小幅调整text


推荐阅读