SVG中的HTML元素未显示

时间:2013-03-01 00:42:52

标签: javascript svg d3.js

我正在使用SVG中的foreignObject。我想在rect中添加文本,并且为了获得自动文本换行,我选择使用HTML。可以找到foreignObject的说明here

我正在使用D3,这是我的数据:

var cds = [
{"uid":"U12","sid":"16","statement":"Movies","x":10,"y":10},
{"uid":"U20","sid":"17","statement":"Food","x":10,"y":170},
{"uid":"U22","sid":"15","statement":"Sport","x":10,"y":330}
];

我为每个数据添加一张卡片,并希望从数据中显示“声明”。

var cardsize = { width : 150, height : 150 };

var svg = d3.select("body").append("svg:svg")
    .attr("width", 170)
    .attr("height", 490);

var card =  svg.selectAll("rect")
    .data(cds)
    .enter().append("svg:g")
    .attr("class", "card")
    .attr("transform", function(d,i) { 
        d.x = 10;
        d.y = 10+i*(10+cardsize.height);
        return "translate(" + d.x + "," + d.y + ")";
    });

card.append("svg:rect")
    .attr('width', cardsize.width)
    .attr('height', cardsize.height)

card.append("svg:foreignObject")
    .attr('width', cardsize.width)
    .attr('height', cardsize.height)
    .append('p')
    .attr("class","statement")
    .text(function(d) { return d.statement; });

卡的输出是:

<g class="card" transform="translate(10,330)">
    <rect width="150" height="150"></rect>
    <foreignObject width="150" height="150"><
        p class="statement">Sport</p>
    </foreignObject>
</g>

我无法在我测试的(mac)浏览器中看到该文本(Safari 6.0.2,Chrome 25.0.1364.99,Firefox 18.0.2)。 W3's validator不喜欢输出,并为每张卡提供此错误:

  

在此上下文中,元素foreignObject不允许作为元素g的子元素。

所以我的问题是,问题出在哪里,为什么不允许foreignObject作为g元素的子元素?

我也想知道为什么.html(function(d) { return d.statement; });不起作用(没有输出)。但.text(function(d) { return d.statement; });工作正常吗?

这是fiddle

2 个答案:

答案 0 :(得分:15)

简短回答

在foreignObject中的所有标记中指定命名空间:将.append("p")替换为.append("xhtml:p"),它将起作用:http://jsfiddle.net/EHzcR/2/


答案很长

在异物的上下文中,<p></p>不会被识别为xhtml段。为什么?只是因为命名空间xhtml未包含在foreignObject上下文中(foreignObject可能包含任何内容(例如xml格式化数据),因此它不会将输入视为如果您没有明确说出来,请使用HTML。)。

因此p标记被视为自定义标记,而不是xhtml标记。因此,由于Web浏览器无法识别它知道的标记中的标记p,因此它只是不解释它及其内容,即使它存在,它也不会抛出错误,因为这个内容可能完全有效,只是不直接使用。

很有趣的是,即使没有必要,也总是指定命名空间svg,以及我们如何忘记pdiv ...也非常有用流行命名空间

selection.html()函数不起作用,因为在implementation中它使用元素的.innerHTML()函数,但是在这里,foreignObject不是html元素,不是有这样的功能。

答案 1 :(得分:0)

我无法从您的问题中判断出您是否可以实际查看foreignObjects中的文本? (如果您的回答是“是”,那么您使用的浏览器是什么?)。

我期待在这里得到其他答案,因为下面的方法对我来说似乎不是最优的,但它确实在那里获得了大部分。

使用Chrome,并根据W3C example尝试在foreignObject内生成<body xmlns="http://www.w3.org/1999/xhtml">标记,然后<p>内的<body>生成文本无法为我所见。但是,只需将内部<body>退出,并添加一个类来设置foreignObject的样式,就会产生所需的结果。

http://jsfiddle.net/6B4zs/5/

更新了下面添加的代码部分:

添加foreignObject文本的D3部分

svg.selectAll("foreignObject")
    .data(cds)
    .enter()
  .append("foreignObject")
    .attr("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility")
    .attr('width', cardsize.width)
    .attr('height', cardsize.height)
    .attr("x", 10)
    .attr("y", function (d, i) { return 10 + i * (10 + cardsize.height) })
    .attr("class", "fo-text")
    .text(function (d) { return d.statement; });

<强> CSS

.fo-text {
    padding: 5px 10px;  
    font: 300 14px "Helvetica Neue", sans-serif;
    color: #000;
}