使用d3在SVG内部渲染foreignObject失败

时间:2013-02-18 17:28:18

标签: javascript svg coffeescript d3.js

我已阅读相关帖子,感觉我的代码准确无误;我也尝试了很多这个代码的突变。我希望有人可以找到我确信我的代码中的一个小错误,因为我没有运气检测它。

问题:在视觉上无法在浏览器中呈现的foreignObject元素的内容。 DOM元素显然已插入DOM但不可见。

我注意到在Chrome Web开发人员中,在元素检查器中,foreignObject元素不是camelcase,但是在编辑html内联时,它可以编辑为camelcase,因此显然该元素被保存为camelcase。这可能对这个问题没有影响,但我想我会提到它。

执行后

DOM:

<g class="component" transform="translate(75,20)">
  <rect width="100" height="100" fill="red" opacity="1">
    <foreignObject width="100" height="100" requiredExtensions="http://www.w3.org/1999/xhtml">
      <body xmlns="http://www.w3.org/1999/xhtml">
        <div style="width: 100px; height: 100px; background-color: yellow;" data-uid="special_uid">
        </div>
      </body>
    </foreignObject>
  </rect>
</g>

D3 SVG / XHTML生成代码(CoffeeScript):

  component = canvas.select("[data-uid=#{entityObj.name}]").selectAll('.component')
    .data(entityObj.components)
    .enter()
    .append("g")
    .each( (componentObj,i,d) => 
      @generateAssociationLocalCache(entityObj,componentObj,i,d)
      @generateComponentLocalCache(entityObj,componentObj,i,d)
    )
    .attr("data-uid", (o,i,d)-> o.name)
    .attr("id", (o,i,d)-> o.name)
    .attr("class", "component")
    .attr("transform", (componentObj,i,d) => 
      coords = @rows[entityObj.name]['components'][componentObj.uid]
      "translate(#{coords.x},#{coords["y#{i}"]})"
    )  
    .append("rect")  
    .attr("width", (componentObj,i,d) => componentObj.width)
    .attr("height", @get('component').height)
    .attr("fill", "red")
    .attr("opacity", "1")
    .append("foreignObject")  
    .attr("width", (componentObj,i,d) => componentObj.width)
    .attr("height", @get('component').height)
    .attr("requiredExtensions", "http://www.w3.org/1999/xhtml")
    .append("body")
    .attr("xmlns","http://www.w3.org/1999/xhtml")
    .append("div")
    .attr("style", (componentObj,i,d) => "width: #{componentObj.width}px; height: #{@get('component').height}px; background-color: yellow;")
    .attr("data-uid", (o,i,d) -> o.uid)

Rendered rect element

1 个答案:

答案 0 :(得分:2)

你至少有2个问题。首先<foreignObject>不能是<rect>元素的子元素。我不确定你想要实现什么,但你可能需要拆分代码

  var g = component.append("g")
    .each( (componentObj,i,d) => 
      @generateAssociationLocalCache(entityObj,componentObj,i,d)
      @generateComponentLocalCache(entityObj,componentObj,i,d)
    )
    .attr("data-uid", (o,i,d)-> o.name)
    .attr("id", (o,i,d)-> o.name)
    .attr("class", "component")
    .attr("transform", (componentObj,i,d) => 
      coords = @rows[entityObj.name]['components'][componentObj.uid]
      "translate(#{coords.x},#{coords["y#{i}"]})"
    )  

然后再做

g.append("rect")  
.attr("width", (componentObj,i,d) => componentObj.width)
.attr("height", @get('component').height)
.attr("fill", "red")
.attr("opacity", "1");

g.append("foreignObject")
...

这将使rect和foreignObject兄弟姐妹。

其次xmlns不是在创建对象后可以设置的属性,所以

.append("body")
  .attr("xmlns","http://www.w3.org/1999/xhtml")

应该是

.append("xhtml:body")
然后,

d3将在正确的命名空间中创建元素。