【问题标题】:HTML element inside SVG not displayed [duplicate]SVG内的HTML元素未显示[重复]
【发布时间】:2013-03-01 00:42:52
【问题描述】:

我正在为 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

【问题讨论】:

标签: javascript svg d3.js


【解决方案1】:

简答

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


长答案

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

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

很高兴看到您总是指定命名空间svg,即使它不是必需的,而且我们都忘记了pdiv... 也有一个非常流行的命名空间。

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

【讨论】:

    【解决方案2】:

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

    我期待这里的其他答案,因为下面的方法对我来说似乎不是最佳的,但它确实可以解决大部分问题。

    使用 Chrome,并尝试根据 W3C example 在 foreignObject 中生成 &lt;body xmlns="http://www.w3.org/1999/xhtml"&gt; 标签,然后在 &lt;body&gt; 中生成 &lt;p&gt;,导致我无法看到文本。但是,只需将内部的&lt;body&gt; 去掉,并添加一个类来设置foreignObject 的样式,就可以产生所需的结果。

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

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

    用于添加外来对象文本的 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;
    }
    

    【讨论】:

    • 谢谢马特。但是您没有将foreignObject 添加到g 对象,这是一个问题,因为在我的实现中我正在拖动这些卡片,所以文本应该是g.card 元素的一部分(否则它们不会移动卡片时标记)。我已经通过拖动jsfiddle.net/E8PmE 更新了小提琴。所以我需要一个解决方案,我有g.card 作为父母,然后rect + foreignObject 作为孩子。
    • 并回答您的问题:我无法查看 foreignObjects 中的文本,但是当我检查元素时,我可以看到文本在 DOM 中。我还用浏览器信息更新了我的问题。
    猜你喜欢
    • 1970-01-01
    • 2012-11-21
    • 2020-09-08
    • 2021-01-29
    • 2019-03-04
    • 2012-07-15
    • 1970-01-01
    • 2014-10-16
    • 2013-06-25
    相关资源
    最近更新 更多