首页 > 解决方案 > D3在文本中动态加粗单词

问题描述

在我的数据中,我得到一个可以包含 1 到 2 个单词(“one”或“one two”)的字符串。如果一个词的字体粗细需要为 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);
}

标签: javascriptd3.jssvg

解决方案


感谢@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}` : ''
})


推荐阅读