6

我正在尝试使用 d3 让文本在 svg 中垂直显示。但是,我不想旋转它:我希望字母保持水平,但一个在另一个之上。设置writing-mode=tb似乎没有做任何事情。这是我尝试过的:

svg.append("text")
  .attr("x", 1000)
  .attr("y", 400)
  .attr("id", "title")
  .attr("font-size", 50)
  .attr("style", "font-family: arial; fill: lightgreen; writing-mode: tb")
  .text("Top 100 Mentions");

文本显示在正确的位置,使用正确的字体等,但它是水平的。

4

5 回答 5

17

当谈到旋转 SVG 文本时,有多个不同的方面:

  • 浏览器如何根据前一个字符的位置确定下一个字符的位置;

  • 字符如何相对于基线(rotate属性)旋转;

  • 最终文本块作为一个整体如何相对于坐标系(transform属性)旋转。

完整的,相当难以理解的规格在这里

'writing-mode' 属性应该改变第一个方面而不影响其他方面,但正如您发现它根本没有在 Firefox 中实现,而 IE 旋转文本但不遵守水平字形规则。

从理论上讲,您应该能够通过组合旋转和变换属性来获得相同的效果:变换整个<text>元素以将其旋转到垂直位置,然后反向旋转单个字符以使其恢复水平。但在实践中,它变得混乱......

对于初学者来说,双重旋转会导致文本位于 (x,y) 点的左侧,因此如果 (x,y) 为 (0,0) 它将被剪切到 SVG 之外而无需补充移位。由于变换,您需要一个负值dy来将文本移回锚点的右侧

其次,旋转应用于每个字符的位置,字符的间距没有调整以解释“l”比它的宽度高得多的事实。所以除非你使用等宽,否则事情看起来很混乱。您应该能够使用kerningandletterspacing属性更改字母间距,但浏览器对这些属性的支持也很差:IE11 似乎不承认字距调整值,而 Firefox 也不承认。

最后一种选择是自己控制布局:使用 d3 的强大功能和 string.split("")方法将标题分解为单字符<tspan>元素,这些元素可以彼此下方放置并在<text>元素内整齐地居中。缺点是这增加了额外的 DOM 元素,您仍然可以选择整个文本块,就像您可以在 HTML 段落中选择一个短语一样,即使每个字母都设置为单独的<span>. 我不确定屏幕阅读器是否会自动假设字母之间有空格,但......

比较

这个小提琴尝试了三种在垂直文本标签中获取水平字符的方法(写作模式vs双旋转vs拆分成<tspan>s):http:
//jsfiddle.net/hx5Th/11/

代码:

var svg = d3.select("body").append("svg");

//Green text, uses writing-mode property //
svg.append("text")
  .attr("x", 40)
  .attr("y", 40)
  .attr("id", "title")
  .attr("font-size", 50)
  .attr("style", "fill: lightgreen; writing-mode: tb; glyph-orientation-vertical: 0")
  .text("Top 100 Mentions");

//Black text, uses a double rotate //
svg.append("text")
  .attr("x", 40)
  .attr("y", 40)
  .attr("id", "title")
  .attr("font-size", 50)
  .attr("rotate", -90)
  .attr("dx", "1em")
  .attr("dy", "-1em")
  .attr("kerning", 0)
  .attr("letter-spacing", "0.5em")
  .attr("transform", "translate(150,0) rotate(90)")
  .text("Top 100 Mentions");

//Blue text, uses d3 to create a series of tspans//
svg.append("text")
  .attr("x", 40)
  .attr("y", 40)
  .attr("font-size", 50)
  .attr("id", "title")
  .style("fill", "blue")
  .attr("transform", "translate(300,0)")
  .attr("text-anchor", "middle")
  .selectAll("tspan")
      .data("Top 100 Mentions".split(""))
  .enter().append("tspan")
      .attr("x", 0)
      .attr("dy", "0.8em")
      .text(function(d){return d;});

结果(全部在 Windows 7 系统上):

铬 33 在此处输入图像描述

即 11 在此处输入图像描述

火狐 在此处输入图像描述

我认为这是胜利的d3...

于 2014-02-28T03:53:26.790 回答
1

嵌入在svg中的html:

<svg
  x="0px" y="0px"
  width="200px" height="200px" 
  viewbox="0 0 200 200"
>

  <foreignObject
    x="20" y="20"
    width="160" height="160"
  >

    <!-- we must set xmlns attribute
      for foreignObject.childNode -->
    <div
      xmlns="http://www.w3.org/1999/xhtml"
      style="

        /* HTML-CSS vertical text */
        writing-mode: vertical-lr;
        text-orientation: upright;

        line-height: 2em;
        font-family: sans-serif;
        font-size: 150%;
      "
    >Hello<br/>&nbsp;World</div>

  </foreignObject>

</svg>

于 2020-02-04T06:35:45.417 回答
0

您可以通过将文本绑定到路径元素来控制文本的位置和方向。下面的示例在 jsFiddle 上运行版本

var svg = d3.select("body").append("svg"),
    pi = Math.PI;

var arc = d3.svg.arc()
    .innerRadius(150)
    .outerRadius(180)
    .startAngle(0)
    .endAngle(-pi/2)

var path = svg.append("path")
    .attr("id","path1")
    .attr("d","M150 150 L150 20 Z")
    .attr("style","stroke:rgb(255,0,0);stroke-width:2")

// Add a text label.
var text = svg.append("text")
    .attr("x", 6)
    .attr("dy", 15);

text.append("textPath")
   .attr("stroke","black")
   .attr("xlink:href","#path1")
   .text("abc");
于 2013-03-15T17:07:34.653 回答
0

这应该做你想做的(虽然我不知道如何在 d3 中表达):

<text x="100" y="100" transform="rotate(90, 100, 100)" style="glyph-orientation-horizo​​ntal: 270;">一些垂直文本没有旋转</text>

显然将 x 和 y 坐标更改为您自己的值。

于 2014-02-27T13:24:35.360 回答
0

对于 Firefox,我能发现他们从 FF 30 开始实现的唯一内容是 textLength。我在 AmeliaBR 的 jsfiddle 中添加了第四个附加文本以进行演示。看起来仍然像废话,D3仍然是赢家。 http://jsfiddle.net/hx5Th/11/

//Black text, uses a double rotate //
svg.append("text")
  .attr("x", 40)
  .attr("y", 40)
  .attr("id", "title")
  .attr("font-size", 50)
  .attr("rotate", -90)
  .attr("dx", "1em")
  .attr("dy", "-1em")
  .attr("textLength", "12.8em")
  .attr("transform", "translate(450,0) rotate(90)")
  .text("Top 100 Mentions");
于 2014-07-08T12:59:41.933 回答