d3中的垂直文本(未旋转) [英] vertical text in d3 (not rotated)

查看:242
本文介绍了d3中的垂直文本(未旋转)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用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);

文本显示在正确的位置,具有正确的字体等, / p>

解决方案

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




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


  • 相对于基线( rotate 属性)旋转;





p> 完整,相当难以理解,此处规范



写入模式属性应该改变第一个方面而不影响其他方面,但当你发现它在Firefox 中没有实现,而IE旋转文本,但不尊重水平字形规则



理论上,您应该能够通过组合rotate和transform属性来获得相同的效果:transform < text> 元素将其旋转到垂直位置,然后反向旋转各个字符以使它们回到水平。但在实践中,它变得乱七八糟...



对于初学者,双旋转会导致文本结束在(x,y)所以如果(x,y)是(0,0),它将被剪切到SVG之外,而不需要补充移位。由于这些转换,您需要一个 dy 将文本移回到锚点的右侧。



其次,存在这样的事实,即旋转被应用于每个字符就位,字符的间距不被调整以说明l高得多比它宽。因此,除非你使用等宽,事情看起来很混乱。您应该能够使用 kerning letterspacing 属性更改字母间距,但浏览器对这些属性的支持也很差:IE11似乎不承认字距值,Firefox也不承认。



最后一个选项是自己控制布局: 使用d3和字符串 .split()方法的力量将标题分成单字符< tspan> / code>元素,它们可以一个放在另一个之下,并且整齐地放在< text> 元素中。缺点是,这增加了额外的DOM元素,你仍然可以选择文本块作为一个整体,就像你可以选择一个HTML段落中的一个短语,即使每个字母样式为一个单独的 < span> 。我不确定屏幕阅读器是否会自动假设字母之间有空格,虽然...



比较



这个小提琴尝试在垂直文本标签中获得水平字符的三种方式(写入模式 vs 双旋转 vs 拆分为 < tspan> s):

http:// jsfiddle .net / hx5Th / 11 /



代码:

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

//绿色文本,使用写入模式属性//
svg.append(text)
.attr(x,40)
。 attr(y,40)
.attr(id,title)
.attr(font-size,50)
.attr fill:lightgreen; writing-mode:tb; glyph-orientation-vertical:0)
.text(Top 100 Mentions);

//黑色文本,使用双旋转//
svg.append(text)
.attr(x,40)
.attr (y,40)
.attr(id,title)
.attr(font-size,50)
.attr )
.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) ;

//蓝色文本,使用d3创建一系列tspans //
svg.append(text)
.attr(x,40)
.attr(y,40)
.attr(font-size,50)
.attr(id,title)
.style ,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系统上):


$ b b

Chrome 33



IE 11



Firefox



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


I am trying to get text to display vertically in svg using d3. I do not want to rotate it, however: I want the letters to remain horizontal, but one above the other. Setting writing-mode=tb does not seem to do anything. Here is what I tried:

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");

The text shows up in the right location, with the right font etc, but it is horizontal.

解决方案

When talking about rotating SVG text, there are multiple different aspects:

  • how the browser determines where to position the next character based on the previous character's position;

  • how the characters are rotated relative to the baseline (rotate attribute);

  • how the final text block as a whole is rotated relative to the coordinate system (transform attribute).

Full, rather difficult to comprehend, specs here.

The 'writing-mode' property is supposed to change the first aspect without affecting the others, but as you discovered it's not implemented at all in Firefox, while IE rotates the text but doesn't respect the horizontal-glyph rule.

Theoretically, you should be able to get the same effect by combining the rotate and transform attributes: transform the entire <text> element to rotate it into a vertical position, then reverse-rotate the individual characters to get them back to horizontal. But in practice, it gets messy...

For starters, the double rotations cause the text to be end up on the left of your (x,y) point, so if (x,y) is (0,0) it will be clipped outside the SVG without supplemental shift. Because of the transforms, you'll need a negative dy value to move the text back to the right of the anchor point.

Second, there is the fact that the rotation is applied to each character in place, the spacing of the characters isn't adjusted to account for the fact that an "l" is much taller than it is wide. So unless you're using monospace, things look pretty jumbled up. You're supposed to be able to change the letter spacing with the kerning and letterspacing properties, but browser support for those is also poor: IE11 doesn't seem to acknowledge the kerning value, and Firefox doesn't acknowledge either.

A final option is to take control of the layout yourself: use the power of d3 and the string .split("") method to break your title into single-character <tspan> elements that can be positioned one below each other and centered neatly within the <text> element. The downside is that this adds extra DOM elements, you can still select the block of text as a whole, just the same as you could select a phrase in an HTML paragraph even if each letter was styled as a separate <span>. I'm not sure if screen readers will automatically assume that there are spaces between the letters, though...

Comparison

This fiddle tries out the three ways to get horizontal characters in a vertical text label (writing-mode vs double rotate vs splitting into <tspan>s):
http://jsfiddle.net/hx5Th/11/

Code:

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;});

Results (all on a Windows 7 system):

Chrome 33

IE 11

Firefox

I think this is d3 for the win...

这篇关于d3中的垂直文本(未旋转)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆