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

时间:2014-03-21 20:54:35

标签: javascript css d3.js nvd3.js

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

tables:
[
  {
    <some descriptors of the dataset>, 
    series: 
    [
      key: ...,
      values: 
        [
          { label: ..., value: ... },
          ...
        ]
    ]
  },
  ...
]

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

由于我对JavaScript不是很有经验,所以我决定安全地使用它并遵循N​​VD3.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;
        }
        );
    }
);

所以,代码很糟糕,但它的工作原理......事情就是这样:它试图绘制每个图表并将其放在div中,但每个图表只显示没有样式的纯文本。见this Imgur album。如果我用一个表的名称“硬编码”一个div,它会在里面绘制图表。对我来说,看起来新创建的div没有应用NVD3.js CSS文件。我甚至不知道这是否可能,因为我对CSS的了解甚至比JavaScript还要少。

有没有人尝试过这样的事情,或者有人知道可能导致这种行为的原因吗?

1 个答案:

答案 0 :(得分:4)

我刚刚遇到这个问题,在浏览了GitHub后我found the problem

  

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

我的问题特别涉及jQuery,这导致我使用:

生成SVG元素
var $svg = d3.select($jqElement[0]).append("svg")

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