d3中的垂直文本(未旋转)

时间:2013-03-15 16:17:10

标签: svg d3.js vertical-text

我正在尝试使用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");

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

5 个答案:

答案 0 :(得分:11)

在谈论旋转SVG文本时,有多个不同方面:

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

  • 字符相对于基线(rotate属性)的旋转方式;

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

Full, rather difficult to comprehend, specs here

'write-mode'属性应该改变第一个方面而不影响其他方面,但是当你发现it's not implemented at all in Firefox时,IE会旋转文本但不尊重水平字形规则。

理论上,你应该能够通过组合旋转和变换属性来获得相同的效果:变换整个<text>元素以将其旋转到垂直位置,然后反向旋转个别角色让他们回到水平。但在实践中,它变得混乱......

对于初学者来说,双重旋转会导致文本在(x,y)点的左边结束,所以如果(x,y)是(0,0),它将被剪切到SVG之外而没有补充转移。由于转换,您需要否定dy才能将文本移回锚点的右侧。

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

最后一个选项是自己控制布局:使用d3的强大功能和字符串.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系统上):

Chrome 33 enter image description here

IE 11 enter image description here

<强>火狐 enter image description here

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

答案 1 :(得分: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>

答案 2 :(得分:0)

您可以通过将文本绑定到路径元素来控制文本的位置和方向。以下示例使用running version on 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");

答案 3 :(得分:0)

这应该做你想要的(尽管我不知道如何在d3中表达它):

&lt; text x =“100”y =“100”transform =“rotate(90,100,100)”style =“glyph-orientation-horizo​​ntal:270;”&gt;一些未旋转的垂直文本&lt; / text&gt ;

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

答案 4 :(得分: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");