javascript - 从数据对象数组创建折线图

标签 javascript d3.js

我在使用 D3 从解析的数据对象数组渲染简单的线图时遇到了这个奇怪的问题。

当我将数据对象数组硬编码到我的代码中时,图表将呈现良好。但是,当我解析 JSON 文件、创建数据对象并将其推送到数组时,它不会渲染...

两个数组(硬编码与解析)具有完全相同的数据,但只有硬编码才会渲染图形。

硬编码数据... ( creates graph )

    var lineData =  [
                        {date: new Date("03/04/15"), rain: "2.2"},
                        {date: new Date("03/05/15"), rain: "2.3"},
                        {date: new Date("03/06/15"), rain: "0.0"},
                        {date: new Date("03/07/15"), rain: "2.0"},
                        {date: new Date("03/08/15"), rain: "5.0"},
                        {date: new Date("03/09/15"), rain: "2.3"},
                        {date: new Date("03/10/15"), rain: "15.0"},
                        {date: new Date("03/11/15"), rain: "0.0"},
                        {date: new Date("03/12/15"), rain: "7.0"},
                        {date: new Date("03/13/15"), rain: "0.0"},
                        {date: new Date("03/14/15"), rain: "1.0"},
                        {date: new Date("03/15/15"), rain: "0.0"},
                        {date: new Date("03/16/15"), rain: "2.3"},
                        {date: new Date("03/17/15"), rain: "8.0"},
                        {date: new Date("03/18/15"), rain: "1.4"},
                        {date: new Date("03/19/15"), rain: "0.0"},
                        {date: new Date("03/20/15"), rain: "1.0"}
                 ];            

var vis = d3.select("#visualisation"),
  WIDTH = 600,
  HEIGHT = 250,
  MARGINS = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 50
  },

xRange = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function (d) {
    return d.date;
  }),
  d3.max(lineData, function (d) {
    return d.date;
  })
]),

yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function (d) {
    return d.rain;
  }),
  d3.max(lineData, function (d) {
    return d.rain * 1.2;
  })
]),

xAxis = d3.svg.axis()
  .scale(xRange)
  .tickSize(5),

yAxis = d3.svg.axis()
  .scale(yRange)
  .tickSize(5)
  .orient("left");

vis.append("svg:g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
  .call(xAxis);

vis.append("svg:g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + (MARGINS.left) + ",0)")
  .call(yAxis);

var lineFunc = d3.svg.line()
  .x(function (d) {
    return xRange(d.date);
  })
  .y(function (d) {
    return yRange(d.rain);
  })
  .interpolate('linear');

vis.append("svg:path")
  .attr("d", lineFunc(lineData))
  .attr("stroke", "blue")
  .attr("stroke-width", .5)
  .attr("fill", "none");

已解析的 JSON ( live example )...

// global variables
var dailyRainTotal = 0,
    lineData = [],
    day = {};

// get the data
d3.json("https://api.myjson.com/bins/53grr", function(error, data) {

    // log the returned object on console unless error
    if (error) return console.error(error);
    console.log(data);

    var days = data.data.weather;

    // step through each day
    days.forEach(function(d) {

        // step through each hour
        d.hourly.forEach(function(h) {
            dailyRainTotal = dailyRainTotal + parseFloat(h.precipMM);
        });

        // add data to day
        day = {date: new Date(d.date), rain: dailyRainTotal.toFixed(2)};
        // push day to results array
        lineData.push(day);

        // reset the total
        dailyRainTotal = 0;
    });
});

var vis = d3.select("#visualisation"),
  WIDTH = 600,
  HEIGHT = 250,
  MARGINS = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 50
  },
xRange = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function (d) {
    return d.date;
  }),
  d3.max(lineData, function (d) {
    return d.date;
  })
]),

yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function (d) {
    return d.rain;
  }),
  d3.max(lineData, function (d) {
    return d.rain * 1.2;
  })
]),

xAxis = d3.svg.axis()
  .scale(xRange)
  .tickSize(5),

yAxis = d3.svg.axis()
  .scale(yRange)
  .tickSize(5)
  .orient("left");

vis.append("svg:g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
  .call(xAxis);

vis.append("svg:g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + (MARGINS.left) + ",0)")
  .call(yAxis);

var lineFunc = d3.svg.line()
  .x(function (d) {
    return xRange(d.date);
  })
  .y(function (d) {
    return yRange(d.rain);
  })
  .interpolate('linear');

vis.append("svg:path")
  .attr("d", lineFunc(lineData))
  .attr("stroke", "blue")
  .attr("stroke-width", .5)
  .attr("fill", "none");

当我检查控制台时,lineData 数组与硬编码数据具有相同的格式和值,但 x/y 轴和线条不会显示。请帮忙!

最佳答案

d3 json 函数是异步的。因此,创建该行的代码是在 json 数据实际到达之前执行的。您需要将行创建代码移至 json 函数中:

d3.json("https://api.myjson.com/bins/53grr", function(error, data) {

    // log the returned object on console unless error
    if (error) return console.error(error);
    console.log(data);

    var days = data.data.weather;

    // step through each day
    days.forEach(function(d) {

        // step through each hour
        d.hourly.forEach(function(h) {
            dailyRainTotal = dailyRainTotal + parseFloat(h.precipMM);
        });

        // add data to day
        day = {date: new Date(d.date), rain: dailyRainTotal.toFixed(2)};
        // push day to results array
        lineData.push(day);

        // reset the total
        dailyRainTotal = 0;
    });

  var vis = d3.select("#visualisation"),
  WIDTH = 600,
  HEIGHT = 250,
  MARGINS = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 50
  },
xRange = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function (d) {
    return d.date;
  }),
  d3.max(lineData, function (d) {
    return d.date;
  })
]),

yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function (d) {
    return d.rain;
  }),
  d3.max(lineData, function (d) {
    return d.rain * 1.2;
  })
]),

xAxis = d3.svg.axis()
  .scale(xRange)
  .tickSize(5),

yAxis = d3.svg.axis()
  .scale(yRange)
  .tickSize(5)
  .orient("left");

vis.append("svg:g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
  .call(xAxis);

vis.append("svg:g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + (MARGINS.left) + ",0)")
  .call(yAxis);

var lineFunc = d3.svg.line()
  .x(function (d) {
    return xRange(d.date);
  })
  .y(function (d) {
    return yRange(d.rain);
  })
  .interpolate('linear');

vis.append("svg:path")
  .attr("d", lineFunc(lineData))
  .attr("stroke", "blue")
  .attr("stroke-width", .5)
  .attr("fill", "none");
});

关于javascript - 从数据对象数组创建折线图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29108215/

相关文章:

javascript - d3.js 中的函数,用于从不同大小的 JSON 源创建开始和结束节点以及节点和链接文本

javascript - jQuery 不会 append 在文档就绪时声明的克隆

javascript - 使文本输入字段记住以前输入的数据

javascript - 如何将垂直网格线添加到我的 d3 图表

javascript - 在节点单击时从 json 获取数据

javascript - D3 Sankey 技术说明中节点的 x 位置

javascript - 使用 jQuery 打开侧边栏窗口

javascript - OSX Safari 上滚动事件期间 CSS 定位无响应且抖动(适用于 Chrome/Firefox)

javascript - 绘制具有 2 个或 3 个彩色区域的密度函数?

javascript - 从jquery触发d3点击