Добавление нескольких svg-текстов с d3

Я застрял в этой проблеме в течение нескольких дней.

Итак, у меня есть набор данных объектов следующего вида:

dataset = [{metric:"revenue",value:0.03},{metric:"sales", value:0.15},{metric:"churn", value: 0.06},{metric:"logins", value: 0.45}]

Следующий код будет отображать 4 метрических имени в шаблоне сетки (meshy, meshx - это точки координат сетки, а meshsize - размер сетки, поэтому это просто помещает текст в середину квадрата сетки ):

svg.selectAll("text")
    .data(dataset)
    .enter()
    .append("text")
    .text(function(d){
        return d.metric;
    })
    .attr("y",function(d,i){
        return meshy[i] + meshsize/2;
    })
    .attr("x", function(d,i){
        return meshx[i] + meshsize/2;
    })
    .attr("font-size",25)
    .attr("font-family","serif")
    .attr("text-anchor","middle")
    .attr("font-weight","bold");

Теперь я хотел бы поставить значение метрики прямо под именем метрики следующим образом:

 svg.append("text")
    .data(dataset)
    .text(function(d){
        return (d.value);
    })
    .attr("y",function(d,i){
        return meshy[i] + meshsize/2 + 20;
    })
    .attr("x", function(d,i){
        return meshx[i] + meshsize/2 ;
    })
    .attr("font-size",25)
    .attr("font-family","serif")
    .attr("text-anchor","middle")
    .attr("font-weight","bold");

Но это только возвращает значение под именем метрики для FIRST-метрики, другие 3-значные тексты даже не в DOM. Я попробовал несколько подходов, включая замену .text на .html, как описано здесь: https://github.com/mbostock/d3/wiki/Selections#wiki-html без успеха. Я также попытался добавить элементы абзаца вместо этого - это работает, но элементы p расположены ниже тела svg в списке без очевидного способа переместить их в нужное положение. Вышеприведенный код ближе всего подходит для получения того, что мне нужно, но по какой-то причине появляется только первый текст значения. Тем не менее, я открыт для любого подхода в d3, который выполняет задание: 4 метрических имени со значениями, расположенными под ними

Ответ 1

В вашем втором блоке кода вы добавляете только один элемент text, поэтому появляется только один из них. Вам нужно добавить текст, похожий на ваш первый блок, т.е. С выбором .enter(). Для этого у вас есть два варианта. Вы можете сохранить или повторно использовать выбор .enter() или назначить разные классы двум типам текста, чтобы они могли различать их.

Вариант 1:

var texts = svg.selectAll("text")
                .data(dataset)
                .enter();

texts.append("text")
     .text(function(d){
                    return d.metric;
                })
     // set position etc.

texts.append("text")
     .text(function(d){
                    return d.value;
                })
     // set position etc.

Вариант 2:

svg.selectAll("text.title")
                .data(dataset)
                .enter()
                .append("text")
                .attr("class", "title")
                .text(function(d){
                    return d.metric;
                })
     // set position etc.

svg.selectAll("text.value")
                .data(dataset)
                .enter()
                .append("text")
                .attr("class", "value")
                .text(function(d){
                    return d.value;
                })
     // set position etc.

Первый вариант явно короче, но в зависимости от того, что еще вы хотите сделать, может быть предпочтительнее второй вариант - если вы захотите впоследствии изменить текст, это будет намного проще, если вы сможете различать два виды текста. Вы также можете использовать разные классы для создания разных стилей CSS.