SVG文字交互区域的制作注意:html object in SVG

SVG文字交互区域的制作注意

 

在很多情况下,我们使用d3(或者其他SVG类库)创建交互式图表时,都需要将html元素插入到SVG元素上。典型的例子,就是图表中有需要交互式修改文字的地方,当用户点击了某个svg text元素,这里我们需要将一个html元素 input“放进”SVG元素中,并在这个input元素上绑定事件,从而快速更改文字。而svg本身元素类型是提供不了类似的功能的,所以用到html元素是必须的。

SVG元素主要有如下几类:svg(定义svg文档片段), rect(定义矩形), circle(定义圆形),ellipse(定义椭圆),path(路径),line(线),ploygon(多边形),text(文字),title(标题), desc(描述), g(群组), defs(参考元素), image(图片元素)。详见:http://www.w3school.com.cn/svg/svg_reference.asp

但是,直接将html元素插入SVG元素内是不可以显示的。

下例,使用d3js设置text元素是可以显示的,但是如果把插入的元素改为div,则div元素虽然可以创建,但是不可见。

 node.append("text")
      .attr("dx", 16)
      .attr("dy", ".0em")
      .text(function(d) { return d.name });

html object in SVG

 

这是使用SVG绘图时经常遇到的问题。有两个解决办法:

1.将div使用SVG元素foreignObject包裹。

这个办法的好处是,通过foreignObject,可以将div元素嵌入SVG片段来处理。详见:http://ajaxian.com/archives/foreignobject-hey-youve-got-html-in-my-svg.

但是此方法不兼容IE任何版本,详见https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/foreignObject

2.将div定义为浮动层,然后使用left, top属性,等计算位置。

用这种方法制作文字提示框,就像这样:

d3.select("#nytg-tooltip").style('top',ypos+"px").style('left',xpos+"px").style('display','block');

这个方法比起第一种,在位置计算上复杂度是一样的。并且浮动的div更容易控制。具体而言这有一个案例:

http://www.nytimes.com/interactive/2012/10/15/us/politics/swing-history.html?_r=0

enter image description here

 

结论:

 

对于要进行交互操作的文字区域,通常要借助html元素的力量来实现效果。将html元素加入SVG有两种方法,其一是将div使用SVG元素foreignObject包裹,其二是将div定义为浮动层,然后使用left, top属性,等计算位置。

这里还要特别提到一个案例:在线思维导图软件mindmo也是这样处理文字区域的交互问题的。它将所有的节点文字区域都用浮动的div显示,使用top,left属性来控制其位置;而svg只用于路径显示。例如:https://www.mindomo.com/mindmap/cd8215d5e5b1427c9c22b4abc6aae5d6