javascript 未显示 SVG 内的 HTML 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15148481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:41:25  来源:igfitidea点击:

HTML element inside SVG not displayed

javascriptsvgd3.js

提问by swenedo

I am struggeling with the foreignObjectin SVG. I want to add text inside a rect, and to get auto text wrap I have chosen to use HTML. The description of foreignObjectcan be found here.

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

I am working with D3, and this is my data:

我正在使用 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}
];

I add a card for each datum and want to display the "statement" from the data.

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

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; });

The output of a card is this:

卡的输出是这样的:

<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>

I can't see the text in the (mac) browsers I have tested (Safari 6.0.2, Chrome 25.0.1364.99, Firefox 18.0.2). W3's validatordoesn't like the output, and give me this error for each card:

我在测试过的 (mac) 浏览器(Safari 6.0.2、Chrome 25.0.1364.99、Firefox 18.0.2)中看不到文本。W3 的验证器不喜欢输出,并为每张卡给我这个错误:

Element foreignObject not allowed as child of element g in this context.

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

So my question is, where is the problem, and why is foreignObject not allowed as a child of a gelement?

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

I am also wondering why .html(function(d) { return d.statement; });doesn't work (no output). But .text(function(d) { return d.statement; });works fine?

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

Here is a fiddle.

这是一个小提琴

回答by Christopher Chiche

Short answer

简答

Specify the namespace in all tags in a foreignObject: replace .append("p")by .append("xhtml:p")and it will work: http://jsfiddle.net/EHzcR/2/

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



Long answer

长答案

In the context of foreign objects, <p></p>is not recognized as a xhtmlparagraph. Why? Simply because the namespace xhtmlis not included in the foreignObjectcontext (a foreignObjectmight contain anything (xmlformated data for example) so it doesn't consider the input as html if you don't explicitly say it.).

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

So the ptag is considered as a custom tag, not as a xhtmltag. Thus, as the web browser doesn't recognize the tag pin the tags it knows, so it just doesn't interpret it and its content, even if it exists, it won't throw an error as well because this content might be totally valid, just not for its direct use.

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

It is fun to see that you always specify the namespace svgeven if it is not necessary and how we all forget that the p, div... also have a very popular namespace.

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

The selection.html()function doesn't work because in its implementationit uses the .innerHTML()function of the element, but here, the foreignObject, not being an html element, doesn't have such a function.

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

回答by mg1075

I can't tell from your question whether or not you can actually view the text in the foreignObjects? (And if your answer is "yes", then what browser are you using?).

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

I'm looking forward to other answers here, because the method below does not seem optimal to me, but it does get most of the way there.

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

Using Chrome, and attempting to generate the <body xmlns="http://www.w3.org/1999/xhtml">tag inside the foreignObject as per the W3C example, and then the <p>inside the <body>, left the text unable to be seen for me. But then just leaving the inner <body>out, and adding a class to style the foreignObject, produced the desired result.

使用 Chrome,并尝试<body xmlns="http://www.w3.org/1999/xhtml">按照W3C 示例在 foreignObject 内部生成标签,然后在<p>内部<body>,让我无法看到文本。但是然后只留下内部<body>,并添加一个类来设置foreignObject的样式,就产生了预期的结果。

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

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

Updated portions of code added below:

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

D3 section for adding foreignObject text

用于添加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

CSS

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