首页 > 前端技术 > SVG文字交互区域的制作注意:html object in SVG
2014
08-03

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元素虽然可以创建,但是不可见。

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属性,等计算位置。

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

这个方法比起第一种,在位置计算上复杂度是一样的。并且浮动的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

 


SVG文字交互区域的制作注意:html object in SVG》有 6 条评论

  1. Pingback 引用通告: d3可视化实战01:理解SVG元素特性 | 张迪的blog

  2. 章梦依 说:

    我用foreignObject嵌入html,再在html使用svg元素text(),这样符合规范吗?为什么text()的元素属性不显示。还有好像google可以显示,其他浏览器都不能显示?这个应该是支持火狐浏览器的吧!
    var htmlDOMs = foreignObjects.append("xhtml:body")
    .attr("width",function(d){
    var arcLength = (radius – innerRadius) * (d.data.score / 100.0);
    return arcLength+"px";
    })//设计新加的html的高度和宽度,宽度是弧长的长度
    .attr("height","14px")
    .style("margin",0)
    .style("padding",0)
    .attr("requiredFeatures","http://www.w3.org/1999/xhtml");
    //body里添加div ,text
    var htmldivs = htmlDOMs.append("xhtml:div")
    .attr("class","textlabel")
    .style("color","black")

    .style("text-align", function(d){
    return d.endAngle > Math.PI ? "right" : "left" ;//文本居于div的右边还是左边
    })
    .append("text")//添加text

    .on(‘mouseover’, tip.show)
    .on(‘mouseout’, tip.hide)//让鼠标移动到文本时也出现tip
    .text(function(d){return d.data.label;})
    .style("text-anchor",function(d){
    return d.endAngle > Math.PI ? "end" : "start" ;
    });

    //text-anchor属性不支持,不显示。

    ——————章梦依记

    • 张迪 张迪 说:

      第一,你这个顺序反了,foreignObject是SVG的元素,其功能是在SVG中载入html元素,而不是在html元素中载入SVG。
      第二,为了浏览器兼容性,我建议还是用“在SVG元素上覆盖html浮动层”的方式来处理这种问题。因为至今IE edge还不支持foreignObject,google chrome偶尔也会出问题。只有火狐是完全支持foreignObject的。

  3. 章梦依 说:

    谢谢您的回复。我明白foreignobject作用是在svg元素中嵌入html。我的意思是先用这个元素在svg嵌入html,再在html中添加svg的元素text()可以吗?

留下一个回复

你的email不会被公开。