在动态创建的 div 上绘制多个 NVD3.js 图表的问题

1 javascript css d3.js nvd3.js

我应该根据具有以下结构的 JSON 文档生成报告:

tables:
[
  {
    <some descriptors of the dataset>, 
    series: 
    [
      key: ...,
      values: 
        [
          { label: ..., value: ... },
          ...
        ]
    ]
  },
  ...
]
Run Code Online (Sandbox Code Playgroud)

JSON 数组中可以有任意数量的表,具有任意系列。当然,每个系列都拥有相同的一组具有不同值的值。对于每个表格,我必须用给定的数据和多条形图绘制一个表格。我选择了 NVD3.js 作为我的图表库。

由于我对 JavaScript 的经验不是很丰富,因此我决定谨慎行事并严格按照 NVD3.js 示例进行操作,并以最古老和最愚蠢的方式生成我需要的 div 和对象。一旦我对 JS 感觉更舒服,我就会实现模板等。这是我的 JavaScript 代码的缩短版本。我知道这很可怕,所以请不要评判我。

var report_data = <stupid way of getting data, will use AJAX later>;

var my_div = document.getElementById('show-report');

report_data.tables.forEach(
    function(table)
    {
        var newDiv = document.createElement('div');
        newDiv.id = 'report_' + table.name;

        var newHeader = document.createElement('h1');
        newHeader.textContent = table.name;
        newDiv.appendChild(newHeader);

                    // Generate style element for chart
        var newStyle = document.createElement('style');
        newStyle.textContent = '#' + table.name + '_chart svg {height: 500px;}';
        newDiv.appendChild(newStyle);

                    // Generate <div><svg /></div> where chart will be placed
        var chartDiv = document.createElement('div');
        chartDiv.id = table.name + '_chart';
        var svgEl = document.createElement('svg');
        chartDiv.appendChild(svgEl);
        newDiv.appendChild(chartDiv);

        // Here I write the table and append it to the main div. Omitted because of intense shame.

        my_div.appendChild(newDiv);

        //Draw chart
        nv.addGraph(
        function() 
        {
            var chart = nv.models.multiBarHorizontalChart()
            .x(function(d) { return d.label })
            .y(function(d) { return d.value })
            .margin({top: 30, right: 20, bottom: 50, left: 175})
            .tooltips(true)
            .showControls(true);

            chart.yAxis
            .tickFormat(d3.format(',.2f'));

            d3.select('#'+ table.name +'_chart svg')
            .datum(table.series)
            .transition().duration(250)
            .call(chart);

            nv.utils.windowResize(chart.update);

            return chart;
        }
        );
    }
);
Run Code Online (Sandbox Code Playgroud)

所以,代码很糟糕,但它有效......有点。事情是这样的:它尝试绘制每个图表并将其放入其 div 中,但每个图表仅以纯文本显示,没有样式。请参阅这张 Imgur 专辑。如果我用我的一个表的名称“硬编码”一个 div,它会在里面毫无障碍地绘制图表。在我看来,新创建的 div 似乎没有应用 NVD3.js CSS 文件。我什至不知道这是否可能,因为我对 CSS 的了解甚至比 JavaScript 还要少。

有没有人尝试过这样的事情,或者有没有人知道是什么导致了这种行为?

Kev*_*own 5

我刚刚遇到了这个问题,在 GitHub 上环顾四周后,我发现了问题

您不能使用 document.createElement 创建 SVG 元素,您必须使用 document.createElementNS 并为 SVG 指定 xml 命名空间,或者只使用 d3 的 append 方法:d3.select(...).append("svg")

我的问题特别涉及 jQuery,这导致我使用以下方法生成 SVG 元素:

var $svg = d3.select($jqElement[0]).append("svg")
Run Code Online (Sandbox Code Playgroud)

对于非 jQuery 用户,可以将常规 DOM 元素传递到d3.select. 在示例中,$jqElement[0]被调用以获取 jQuery 对象的 DOM 版本。