d3js多线图,用多个嵌套对象迭代多个嵌套数组

时间:2015-10-22 12:24:58

标签: javascript json d3.js graph

我是d3js的新手,我正在构建一个如下所示的多线图:

enter image description here

下面列出的数据集样本。

 {
 "cognitive": [{
     "score": 18296.129,
     "timestamp": 1444795200000,
     "count": 152
 }, {
     "score": 17413.408,
     "timestamp": 1444881600000,
     "count": 146
 }, {
     "score": 13893.5,
     "timestamp": 1444968000000,
     "count": 87
 }, {
     "score": 11139.98,
     "timestamp": 1445054400000,
     "count": 71
 }, {
     "score": 8268.798,
     "timestamp": 1445140800000,
     "count": 44
 }, {
     "score": 11507.722,
     "timestamp": 1445227200000,
     "count": 85
 }, {
     "score": 12146.143,
     "timestamp": 1445313600000,
     "count": 107
 }],
 "blumix": [{
     "score": 8232.498,
     "timestamp": 1444795200000,
     "count": 62
 }, {
     "score": 7778.5425,
     "timestamp": 1444881600000,
     "count": 58
 }, {
     "score": 6566.0786,
     "timestamp": 1444968000000,
     "count": 52
 }, {
     "score": 4971.932,
     "timestamp": 1445054400000,
     "count": 39
 }, {
     "score": 4448.755,
     "timestamp": 1445140800000,
     "count": 20
 }, {
     "score": 6997.92,
     "timestamp": 1445227200000,
     "count": 59
 }, {
     "score": 7539.2417,
     "timestamp": 1445313600000,
     "count": 62
 }]

}

我正在使用jQuery Ajax请求获取此Object并将其传递给我的buildGraph函数。

    Graph.utility.loadJson = function(){
    var url = "../../App/assets/JSON/data.json",
        dfd = new $.Deferred();

    d3.json(url, function(error, json){
        var err = !!error;
        if (err) {
            dfd.reject(error);
        }else {
            dfd.resolve(json.cognitive);
        }
    });
    return dfd.promise();
};

这是我用来构建图形的buildGraph函数的片段。

        var x = d3
            .time
            .scale()
            .range([margin.left, W - margin.right]);

        var y = d3.scale
            .linear()
            .range([H - margin.top - 30, 10]);

        var xAxis = d3.svg
                .axis()
                .scale(x)
                // .tickSize(H)
                .orient("bottom")
                .ticks(d3.time.days)
                .tickFormat(d3.time.format("%a %d"))
                .ticks(8);

        var yAxis = d3.svg
                .axis()
                .scale(y)
                .orient("left");

        // Build Lines
        var line = d3.svg.line()
            .x(function(d) { return x(d.timestamp); })
            .y(function(d) { return y(d.score); }); // .interpolate("basis");

        var svg = d3.select("#d3-graph-js")
                    .append("svg")
                    .attr("id", "chart")
                    .attr("width", W)
                    .attr("height", H)
                    .attr("transform", "translate(0," + (H - margin.bottom) + ")")
                    .attr("viewBox", "0 0 " + W + " " + H)
                    .attr("preserveAspectRatio", "xMidYMid")
                    .append("g")
                    .attr("id", "g-chart");

        // data.forEach(function(d, i){
        //  d.timestamp = new Date(d.timestamp);
        // });

        // x.domain([data[0].timestamp, data[data.length - 1].timestamp]);
        // y.domain(d3.extent(data, function(d) { return d.score; }));

        x.domain(d3.extent(data, function(d) { return d.timestamp;}));
        y.domain(d3.extent(data, function(d) { return d.score; }));

当前代码在图中只生成了一行,因为我已经将json.cognitive传递给了buildGraph方法。如果我尝试在我的dfd.resolve(json)中传递Object并尝试使用

迭代Object
for (key in data) {
    var obj = key;
    for (newObj in obj) {
        // Insert the above snippet here
    }
}

这会创建多行,但yAxis的范围从“cognotive”和“bluemix”

如何重写此代码,使其占据Object中所有节点的范围,并在图形上构建多行。

1 个答案:

答案 0 :(得分:0)

您不能只在循环中插入所有图表代码。您的图表代码可以完成所有操作 - 包括域确定和轴创建。您需要做的是修改代码以接受行对象列表。

例如,如果您的数据对象需要两个维度数组:

data = [
    [{score:10,timestamp:x},{...}....],
    [{score:10,timestamp:x},{...}....]
]

然后你可以修改绘制这样的行的代码:

var lines = svg.selectAll(".lines")
        .data(data)
        .enter()
        .append("path")
        .attr("class", "line")
        .attr("d", function(d) {
            return line(d);
        })
        .style("fill", "none");

你可以看到你仍然会使用你的函数告诉d3 x和y坐标的值在哪里。

此外,如果您的代码段使用行列表,则需要修改指定域的代码,此行:

x.domain(d3.extent(data, function(d) { return d.timestamp;}));

必须替换为:

x.domain(d3.extent(data[0], function(d) { return d.timestamp;}));

但请注意,如果您的所有行都具有相同的最小值和最大值(位于同一域中),则您的图表可能会起作用。否则你将不得不修改代码。

我花了一些时间为我的需求创建一个图表库(https://github.com/hoonzis/KoExtensions),最后它几乎总是更容易占用现有的库,除非你想在将来调整它。 / p>