【问题标题】:d3js multi-line graph to iterate multiple nested arrays with multiple nested objectsd3js 多线图用多个嵌套对象迭代多个嵌套数组
【发布时间】:2015-10-22 12:24:57
【问题描述】:

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

下面列出的数据集的样本。

 {
 "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 请求来获取此对象并将其传递给我的 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 函数的 sn-p。

        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) 中传递对象并尝试使用

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

这会创建多条线,但 yAxis 的范围是“认知”和“bluemix”

如何重写此代码,以便它获取对象中所有节点的范围并在图表上构建多条线。

【问题讨论】:

    标签: javascript json d3.js graph


    【解决方案1】:

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

    例如,如果您的数据对象想要二维数组:

    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");
    

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

    此外,如果您的 sn-p 使用行列表,您将需要修改指定域的代码,此行:

    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),最后使用现有的库几乎总是更容易,除非你想在未来对其进行调整。

    【讨论】:

    • 不确定我是否理解以下评论“您的图表可能仅在您的所有线具有相同的最小值和最大值(位于同一域中)时才有效。”我的最小域将始终为 0,并且将 data.score 中的最大值设为最大值。另外,我需要重组我的 JSON 对象吗?
    • 我认为最好重构您的 json 对象并构建一个 line 对象数组。正如我建议的那样,代码将起作用。关于域,由于您有多行,因此可以有多个最大值。因此,整个图表的最终域将类似于:[0,max(allLines)]
    • 关于如何使用当前数据结构的任何建议?修改 JSON 超出了我的能力范围,因为它来自使用他们的 API 的 3rd 方服务。 JSON is object 按关键字分组,每个关键字都附有支持数据。其他信息需要在鼠标悬停在行上的每个节点上显示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多