9

foreignObject在 SVG 中苦苦挣扎。我想在 a 中添加文本rect,并获得自动文本换行,我选择使用 HTML。的描述foreignObject可以在这里找到。

我正在使用 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 的验证器不喜欢输出,并为每张卡给我这个错误:

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

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

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

这是一个小提琴

4

2 回答 2

15

简短的回答

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


长答案

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

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

有趣的是,svg即使没有必要,您也总是指定命名空间,而且我们都忘记了p, div... 也有一个非常流行的命名空间。

selection.html()函数不起作用,因为在它的实现中它使用了.innerHTML()元素的函数,但是这里的foreignObject,不是一个html元素,没有这样的函数。

于 2013-03-01T09:02:05.873 回答
0

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

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

使用 Chrome,并尝试根据W3C 示例<body xmlns="http://www.w3.org/1999/xhtml">在 foreignObject 中生成标签,然后在内部,让我看不到文本。但是,只需将内部排除在外,并添加一个类来设置 foreignObject 的样式,就可以产生所需的结果。<p><body><body>

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;
}
于 2013-03-01T02:27:16.387 回答