首页 > 解决方案 > d3.create() 返回带有 .node() 的元素,但不显示在浏览器中

问题描述

  1. 我正在尝试让 D3.js 使用d3.create()生成矩形元素。它不起作用/显示。

  2. 首先,我创建了一个rectangle()函数,它返回一个元素:

    function rectangle() {
    
        _el = d3.create("rect")
            .attr("stroke", "black")
            .attr("fill", "black")
            .attr("stroke-width", "10px")
            .attr("x", 0)
            .attr("y", 0)
            .attr("width", 300)
            .attr("height", 200);
    
        return _el
    
    }
    
  3. 然后我创建一个 SVG 选择,在其中添加一个rectangle().node()实例:

    
    const SVG_WIDTH = 1000;
    const SVG_HEIGHT = 1000;
    
    svg = d3.select("body").append("svg")
        .attr("width", SVG_WIDTH)
        .attr("height", SVG_HEIGHT)
        .attr("id", "generated")
    
    svg.append(
        // () => rectangle().node()
        function () { return rectangle().node() }
    )
    
  4. 然而,我的浏览器(谷歌浏览器)中没有视觉输出。

  5. 但是,当我查看 DOM(通过 Chrome 的“元素”选项卡)时,D3 生成了正确的 SVG/矩形代码:

    <svg width="1000" height="1000" id="generated">
        <rect stroke="black" fill="black" stroke-width="10px" x="0" y="0" width="300" height="200" rx="10" ry="10"></rect>
    </svg>
    
  6. 事实上,如果我复制上面的代码并将其放置在我的 HTML 文件中的任何其他位置而不进行修改,我的浏览器中就会出现一个矩形。

  7. 为什么 SVG 对浏览器 DOM 的修改没有显示/工作,但它生成的代码是正确的,并且在手动复制/粘贴到 HTML 时会显示?

标签: javascriptsvgd3.js

解决方案


来自d3.create 文档

此方法假定 HTML 命名空间,因此您必须在创建 SVG 或其他非 HTML 元素时明确指定命名空间 [...]

    d3.create("svg") // equivalent to svg:svg  
    d3.create("svg:svg") // more explicitly  
    d3.create("svg:g") // an SVG G element  
    d3.create("g") // an HTML G (unknown) element  

因此,创建矩形的函数应该使用svg:rect. 否则它将创建一个“HTML rect”而不是“SVG rect”。

默认情况下,该d3.create方法在 HTML 命名空间中创建元素。当您使用时,d3.create('rect')您不会创建一个 SVG 矩形,而是一个 HTML 矩形(在 HTML 规范中不存在)。该元素出现在 DOM 中,但浏览器不知道如何渲染它(它具有 SVG 元素的名称,但不是 SVG 元素),因此它不会出现在屏幕上。

每个 HTML 元素都有一个隐xhtml:式前缀,并且 SVG 中的每个 SVG 元素都隐式地有一个svg:前缀。通常你不需要担心它,因为命名空间通常足够明显,可以由库处理。但是,d3.create不能说你想要哪个,因为它是一个分离的元素;所以它默认为 HTML。

因此,即使两者在 DOMsvg:rectxhtml:rect具有相同的名称,它们也引用了不同的规范,并且唯一对浏览器有意义的是svg:rect.


推荐阅读