javascript - D3.js v4+ : truncate text to fit in fixed space

标签 javascript d3.js

在我们通过 d3 操作的 SVG 中要求文本元素的情况并不少见,例如分类刻度标签。这有点不幸,因为 <text> SVG 中的元素不是最好的...呈现的字体大小通常略大于人们认为字体应该占用的大小。例如,如果选择宽度/高度比为 0.6 的等宽字体(例如,如果字体大小为 12px,则字符的宽度应为 7.2px),元素的计算边界矩形可能为 14.2px by n*8px 其中 n 是字符数。

使问题进一步复杂化的事实是,人们经常使用非等宽字体。

chop “太长”的字符串很容易

string.slice(0, numChars-3)+'...'

但是知道适合固定宽度的正确字符数似乎并不简单。

function truncateText(t, text, space) {
  // make sure it is a string
  text = String(text)
  // set text
  t.text(text)
  // get space it takes up
  var rect = t.node().getBoundingClientRect()

  while (Math.max(rect.width, rect.height) > space) {
    text = text.slice(0, text.length - 1)
    t.text(text + '...')
    rect = t.node().getBoundingClientRect()
    if (text.length == 0) break
  }
}

上面的函数采用 d3.selection,文本和文本应该适合的空间。通过不断地操纵 DOM,我们可以获得完美的适合,但是这在计算上非常昂贵。

澄清一下,为了让文本适合固定空间,我的意思是如果我有一个字符串 var string = "this is my very long string" ,我希望呈现字符串的方向(从左到右,即我们正在查看字符串长度)适合固定空间(例如 var fixedSpace = 100 //px )

上面的 chop 文本函数只适用于少数几个字符串,但如果有很多字符串调用这个函数,它就会变得迟钝。

当然,我们可以通过只选择最长的字符串进行优化,计算该字符串的 truncateText,并将字符数作为结果(尽管这仍然有些错误,因为并非所有字符都具有相同的宽度)。

有没有更有效的方法用d3将文本 chop 到固定空间

最佳答案

我同意您建议的方法计算量大,但这是我能想到的唯一方法。但是,如果您只是偶尔运行它(即仅在页面加载时,而不是在鼠标悬停时),那么它应该不会太糟糕,具体取决于您将它应用到多少文本元素。

您可能想尝试将您的方法的性能与 this example by Mike Bostock 中的方法进行比较,它使用 node().getComputedTextLength() 而不是 node().getBoundingClientRect() 并按单词拆分文本:

function wrap(text, width) {
  text.each(function() {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (tspan.node().getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

PS/有一个 CSS technique for truncating text with an ellipsis ,但不幸的是it doesn't work in SVG :(

关于javascript - D3.js v4+ : truncate text to fit in fixed space,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50579535/

相关文章:

javascript - 如何在 Chrome 插件中使用外部 ajax 响应

javascript - 网站的管理部分?

javascript - ng-if 条件具有类名条件

javascript - 将一条线附加到面积图 d3 中路径的末尾

javascript - 设置 d3.curveBundle.beta 似乎没有效果

javascript - 使用纯js创建属性时如何做某事

javascript - 在 JavaScript 中从字符串生成随机数

javascript - 为什么我的 d3 map 函数返回未定义的源属性?

javascript - 如何创建倾斜轴?

javascript - 来自 csv 数据的新数组