Невозможно добавить текст к горизонтальным полосам d3

Я использую следующую горизонтальную гистограмму (http://bl.ocks.org/juan-cb/ab9a30d0e2ace0d2dc8c), который обновляется в зависимости от выбора. Я пытаюсь добавить метки к столбцам, которые будут отображать значение внутри каждого столбца. Не знаю, где я ошибаюсь. Изначально у меня были прямоугольные элементы SVG, которые я сгруппировал под элементом «g» и попробовал таким образом, но все равно не повезло. Любая помощь будет оценена!

JsFiddle — https://jsfiddle.net/b772s5mg/3/

JS

  datasetTotal = [
        {label:"Category 1", value:19},
        {label:"Category 2", value:5},
        {label:"Category 3", value:13},
        {label:"Category 4", value:17},
        {label:"Category 5", value:21},
        {label:"Category 6", value:25}
    ];

    datasetOption1 = [
        {label:"Category 1", value:22},
        {label:"Category 2", value:33},
        {label:"Category 3", value:4},
        {label:"Category 4", value:15},
        {label:"Category 5", value:36},
        {label:"Category 6", value:0}
    ];

    datasetOption2 = [
        {label:"Category 1", value:10},
        {label:"Category 2", value:20},
        {label:"Category 3", value:30},
        {label:"Category 4", value:5},
        {label:"Category 5", value:12},
        {label:"Category 6", value:23}
    ];

    d3.selectAll("input").on("change", selectDataset);

    function selectDataset()
    {
        var value = this.value;
        if (value == "total")
        {
            change(datasetTotal);
        }
        else if (value == "option1")
        {
            change(datasetOption1);
        }
        else if (value == "option2")
        {
            change(datasetOption2);
        }
    }

    var margin = {top: (parseInt(d3.select('body').style('height'), 10)/20), right: (parseInt(d3.select('body').style('width'), 10)/20), bottom: (parseInt(d3.select('body').style('height'), 10)/20), left: (parseInt(d3.select('body').style('width'), 10)/5)},
            width = parseInt(d3.select('body').style('width'), 10) - margin.left - margin.right,
            height = parseInt(d3.select('body').style('height'), 10) - margin.top - margin.bottom;

    var div = d3.select("body").append("div").attr("class", "toolTip");

    var formatPercent = d3.format("");

    var y = d3.scale.ordinal()
            .rangeRoundBands([height, 0], .2, 0.5);

    var x = d3.scale.linear()
            .range([0, width]);

    var xAxis = d3.svg.axis()
            .scale(x)
            .tickSize(-height)
            .orient("bottom");

    var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left");
    //.tickFormat(formatPercent);

    var svg = d3.select("body").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 + ")");

    svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

    d3.select("input[value=\"total\"]").property("checked", true);
    change(datasetTotal);

    function change(dataset) {

        y.domain(dataset.map(function(d) { return d.label; }));
        x.domain([0, d3.max(dataset, function(d) { return d.value; })]);

        svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(xAxis);

        svg.select(".y.axis").remove();
        svg.select(".x.axis").remove();

        svg.append("g")
                .attr("class", "y axis")
                .call(yAxis)
                .append("text")
                .attr("transform", "rotate(0)")
                .attr("x", 50)
                .attr("dx", ".1em")
                .style("text-anchor", "end")
                .text("Option %");


        var bar = svg.selectAll(".bar")
                .data(dataset, function(d) { return d.label; })
        // new data:
        .enter().append("g").append("rect")
                .attr("class", "bar")
                .attr("x", function(d) { return x(d.value); })
                .attr("y", function(d) { return y(d.label); })
                .attr("width", function(d) { return width-x(d.value); })
                .attr("height", y.rangeBand());

                bar.append("text")
    .attr("x", function(d) { return x(d) - 3; })
    .attr("y", 30)
    .attr("dy", ".35em")
    .text(function(d) { return d.value; });


        var bars = d3.select("svg").selectAll("g.rects").data(dataset);

        // removed data:
        bars.exit().remove();

        // updated data:
        bars.transition()
                .duration(750)
                .attr("x", function(d) { return 0; })
                .attr("y", function(d) { return y(d.label); })
                .attr("width", function(d) { return x(d.value); })
                .attr("height", y.rangeBand());

    };

person sparta93    schedule 10.01.2017    source источник


Ответы (2)


Вы можете подумать, что добавляете элементы <text> к элементам <g> (группы), но это не так!

В тот момент, когда ты это сделаешь...

.enter().append("g").append("rect")

... теперь вы пытаетесь добавить текстовые элементы к <rect> элементам, и это не сработает.

Решение: сломайте переменную bars:

//appending the <g> elements
var bar = svg.selectAll(".bar")
    .data(dataset, function(d) {
        return d.label;
    })
    .enter().append("g");

//now you append the <rect> to the <g>
bar.append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
        return x(d.value);
    })
    .attr("y", function(d) {
        return y(d.label);
    })
    .attr("width", function(d) {
        return width - x(d.value);
    })
    .attr("height", y.rangeBand());

//and then you append the <text> to the <g>
bar.append("text")
    .attr("x", function(d) {
        return x(d.value) - 3;
    })
    .attr("text-anchor", "end")
    .attr("y", function(d) {
        return y(d.label) + y.rangeBand() / 2;
    })
    .attr("dy", ".35em")
    .text(function(d) {
        return d.value;
    });

Вот ваша обновленная скрипта: https://jsfiddle.net/v8razxc8/

person Gerardo Furtado    schedule 10.01.2017
comment
Я получаю 404 на скрипке. - person sparta93; 10.01.2017
comment
Попробуйте снова. Я всегда удаляю свое имя пользователя из скрипок, которые я разветвляю, в процессе возникла какая-то проблема. - person Gerardo Furtado; 10.01.2017
comment
Спасибо! Теперь я вижу метки, но график не будет обновляться в зависимости от выбора переключателя. - person sparta93; 10.01.2017
comment
Ну, это еще один вопрос. Проблема в этом настоящем вопросе была правильно исправлена. Здесь, в С.О. советуем не задавать несколько вопросов в одном посте или, что еще хуже, задавать вопросы в комментариях. Таким образом, закройте этот вопрос как решенный и опубликуйте другой вопрос, касающийся этой другой проблемы. - person Gerardo Furtado; 10.01.2017
comment
Да, лучше! У вас будет больше людей, которые смотрят на это. Если вы спросите здесь, в комментариях, я, наверное, единственный, кто это читает. - person Gerardo Furtado; 10.01.2017
comment
К вашему сведению, на случай, если вы захотите пройти мимо. Благодарю. stackoverflow.com/questions/41560077/ - person sparta93; 10.01.2017

Я предпочитаю добавлять прямоугольник и текст внутрь элемента g, а затем преобразовывать в положение. https://jsfiddle.net/sjp700/b772s5mg/4/

 var bar = svg.selectAll(".bar")
                .data(dataset, function(d) { return d.label; })
        // new data:
       var bar_g = bar.enter().append("g")
             .attr("transform", function (d) { return "translate(" + x(d.value) + "," + y(d.label) + ")"; });


        bar_g.append("rect")
                .attr("class", "bar")            
                .attr("width", function(d) { return width-x(d.value); })
                .attr("height", y.rangeBand());


         bar_g.append("text")
           .attr("transform", function (d) { return "translate(" + 10 + "," + 10 + ")"; })
           .attr("y", 30)
           .attr("dy", ".35em")
           .text(function(d) { return d.value; 

});

person user3359706    schedule 10.01.2017