D3 динамически жирные слова в тексте - PullRequest
0 голосов
/ 31 марта 2020

В моих данных я получаю строку, которая может содержать от 1 до 2 слов («один» или «один два»). Если для одного слова значение шрифта должно быть 700, для двух слов первое слово должно содержать 400, а второе - 700. Мой подход заключался в том, чтобы добавить текст отдельно, что по большей части работает, но сложно убедиться, что они всегда сидят в одном и том же месте рядом друг с другом. Есть ли лучший способ сделать это в текстовом пути?

function drawArcLabels(svg, arcs, groupId) {

 const text = svg
    .selectAll(".donutText")
    .data(arcs)
    .enter()

    text
    .append("text")
    .attr("class", d => {
      const classes = `${groupId}Text color-${d.data.name}`;
      return classes;
    })
    // Move the labels below the arcs for those slices with an end angle greater than 90 degrees
    .attr("dy", (d, i) =>
      d.startAngle > 4.4 ? 17 : d.endAngle > (90 * Math.PI) / 180 ? -8 : 17
    )
    .append("textPath")
    .style("text-anchor", "middle")
    .attr("startOffset", function(d) {
      const secondWord = d.data.name.split(' ')[1]
      const firstWord = d.data.name.split(' ')[0]
      if (secondWord) {
        return `${50 - (firstWord.length) / 0.47}%`
      }
      return '50%'
    })
    .attr("fill", "#fff")
    .attr("href", (d, i) => `#${groupId + i}`)
    .text(d => d.data.name.toUpperCase().split(' ')[0])
    .attr("font-size", 11)
    .attr("font-weight", function(d) {
      return d.data.name.split(' ')[1] ? 400 : 900
    })

    text
    .append("text")
    .attr("class", d => {
      const classes = `${groupId}Text color-${d.data.name}`;
      return classes;
    })
    // Move the labels below the arcs for those slices with an end angle greater than 90 degrees
    .attr("dy", (d, i) =>
      d.startAngle > 4.4 ? 17 : d.endAngle > (90 * Math.PI) / 180 ? -8 : 17
    )
    .append("textPath")
    .style("text-anchor", "middle")
    .attr("startOffset", function(d) {
      const firstWord = d.data.name.split(' ')[0]
      const secondWord = d.data.name.split(' ')[1]
      if (secondWord) {
        return '60%'
        //return (50 + (Math.floor((secondWord.length / 2) * 3))) + "%"
      }
    })
    .attr("fill", "#fff")
    .attr("href", (d, i) => `#${groupId + i}`)
    .text(d => d.data.name.toUpperCase().split(' ')[1])
    .attr("font-size", 11)
    .attr("font-weight", 900);
}

1 Ответ

0 голосов
/ 31 марта 2020

Спасибо @RobertLongson за предложение использовать tspan. Мое решение состояло в том, чтобы просто добавить tspan в конце и обрабатывать его как текстовую строку.

function drawArcLabels(svg, arcs, groupId) {

 const text = svg
    .selectAll(".donutText")
    .data(arcs)
    .enter()

    text
    .append("text")
    .attr("class", d => {
      const classes = `${groupId}Text color-${d.data.name}`;
      return classes;
    })
    // Move the labels below the arcs for those slices with an end angle greater than 90 degrees
    .attr("dy", (d, i) =>
      d.startAngle > 4.4 ? 17 : d.endAngle > (90 * Math.PI) / 180 ? -8 : 17
    )
    .append("textPath")
    .style("text-anchor", 'middle')
    .attr("startOffset", '50%')
    .attr("fill", "#fff")
    .attr("href", (d, i) => `#${groupId + i}`)
    .text(d => d.data.name.toUpperCase().split(' ')[0])
    .attr("font-size", 11)
    .attr("font-weight", function(d) {
      return d.data.name.split(' ')[1] ? 400 : 900
    })
    .append('tspan')
    .text(d =>{ 
      const secondWord = d.data.name.toUpperCase().split(' ')[1]
      return secondWord ? ` ${secondWord}` : ''
})
...