在这个d3.js日历视图中包含json?

时间:2017-05-16 21:18:04

标签: javascript jquery html json d3.js

我是d3图表和javascript的新手,这是一场艰苦的战斗。

经过一番研究,我能够用CSV文件填充图表。现在,我正在尝试使用json数据填充图表。

这是我的代码。它松散地基于this example。但我更喜欢使用我的代码(即d3.v4):

var width = 960,
  height = 136,
  cellSize = 17;

var color = d3.scaleQuantize()
  .domain([9000, 12000])
  .range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
var dateParse = d3.timeFormat("%Y-%m-%d");
var svg = d3.select("body")
  .selectAll("svg")
  .data(d3.range(2017, 2018))
  .enter().append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

svg.append("text")
  .attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
  .attr("font-family", "sans-serif")
  .attr("font-size", 10)
  .attr("text-anchor", "middle")
  .text(function(d) {
    return d;
  });

var rect = svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#ccc")
  .selectAll("rect")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("rect")
  .attr("width", cellSize)
  .attr("height", cellSize)
  .attr("x", function(d) {
    return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
  })
  .attr("y", function(d) {
    return d.getDay() * cellSize;
  })
  .datum(d3.timeFormat("%Y-%m-%d"));

svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#000")
  .selectAll("path")
  .data(function(d) {
    return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("path")
  .attr("d", pathMonth);

d3.json("data3.json", function(error, data) {
  //populating data since i don't have the file
  data = [{
    "date": "2017-01-04",
    "open": 10430.69
  }, {
    "date": "2017-01-05",
    "open": 10584.56
  }];

  data.forEach(function(d) {
    d.dd = dateParse(new Date(d.date));
    console.log(d.dd);
  });

  var nest = d3.nest()
    .key(function(d) {
      return d.dd;
    })
    .map(data);

  rect.filter(function(d) {
      return d in data;
    })
    .attr("fill", function(d) {
      return color(data[d]);
    })
    .append("title")
    .text(function(d) {
      return d + ": " + data[d];
    });
});

function pathMonth(t0) {
  var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
    d0 = t0.getDay(),
    w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
    d1 = t1.getDay(),
    w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
  return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
    "H" + w0 * cellSize + "V" + 7 * cellSize +
    "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
    "H" + (w1 + 1) * cellSize + "V" + 0 +
    "H" + (w0 + 1) * cellSize + "Z";
}
<script src="http://d3js.org/d3.v4.min.js"></script>

2 个答案:

答案 0 :(得分:2)

您的代码需要进行一些更改才能正常工作。与d3 v3相比,这些主要与使用data代替nest以及d3 v4中的微小更改(我无法找到相关信息)有关。

过滤

首先,您没有正确过滤数据:

您不希望像这样过滤:

return d in data;

in运算符用于对象的属性,data是一个数组。 您希望通过嵌套进行过滤(如示例中所示):

return d in nest;

其次,至少在我的简短测试中,d3.nest在d3 v4中表现略有不同(这可能取决于版本,我在下面的代码段中使用了4.9.1(min))。当使用以数字开头的键时,d3似乎在使用d3.nest时在每个键的开头附加一个美元符号:

D3v4示例:

&#13;
&#13;
data = [{
    "date": "2017-01-04", "open": 10430.69
  }, {
    "date": "2017-01-05", "open": 10584.56
  }];

  var nest = d3.nest()
    .key(function(d) { return d.date; })
    .map(data);
	
	console.log(nest);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
&#13;
&#13;

与D3v3相比:

&#13;
&#13;
data = [{
    "date": "2017-01-04", "open": 10430.69
  }, {
    "date": "2017-01-05", "open": 10584.56
  }];

  var nest = d3.nest()
    .key(function(d) { return d.date; })
    .map(data);
	
	console.log(nest);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;

如果您看到此行为,则需要相应更改过滤器:

return ("$" + d) in nest;

访问Nest属性

第三,由于data只是一个数组,data[d]不太可能获得所需的结果,因为d将是一个日期字符串,您需要访问nest宾语。记录nest可能有助于找到合适的属性。而不是:

return color(data[d]);

尝试:

return color(nest[("$" + d)][0].open);

这与问题中的链接示例非常相似(除了美元符号之外)。

<强>优化

与您最近的其他question相关,此代码

&#13;
&#13;
    var date = "2017-01-02";
    var dateParse = d3.timeFormat("%Y-%m-%d");
    console.log(dateParse(new Date(date)));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
&#13;
&#13;

什么都不做。它接受一个表示日期的字符串并将其转换为日期对象,然后将其转换回您开始使用的相同字符串表示形式。您可以删除这部分代码,它在链接示例中使用,因为它是从m / d / Y日期字符串转换为日期对象,然后转换为Y-m-d日期字符串。您的初始日期格式已经是您想要的格式,因此无需对其进行修改。只使用:

  var nest = d3.nest()
    .key(function(d) {
      return d.date;
    })
    .map(data);

而不是:

  data.forEach(function(d) {
    d.dd = dateParse(d.date);
  });

  var nest = d3.nest()
    .key(function(d) {
      return d.dd;
    })
    .map(data);

<强>结果

这些更改(我删除了文本以使示例更简单,删除了外部文件引用等)导致:

&#13;
&#13;
var width = 960,
  height = 136,
  cellSize = 17;

var color = d3.scaleQuantize()
  .domain([9000, 12000])
  .range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
  
var dateFormat = d3.timeFormat("%Y-%m-%d");

var svg = d3.select("body")
  .selectAll("svg")
  .data(d3.range(2017, 2018))
  .enter().append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

var rect = svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#ccc")
  .selectAll("rect")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("rect")
  .attr("width", cellSize)
  .attr("height", cellSize)
  .attr("x", function(d) {
    return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
  })
  .attr("y", function(d) {
    return d.getDay() * cellSize;
  })
  .datum(dateFormat);

svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#000")
  .selectAll("path")
  .data(function(d) {
    return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("path")
  .attr("d", pathMonth);

  data = [{
    "date": "2017-01-04",
    "open": 10430.69
  }, {
    "date": "2017-01-05",
    "open": 10584.56
  }];

  var nest = d3.nest()
    .key(function(d) {
      return d.date;
    })
    .map(data);

	rect.filter(function(d) {
      return ("$" + d) in nest;
    })
    .attr("fill", function(d) { 
      return color(nest[("$" + d)][0].open);
    })


function pathMonth(t0) {
  var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
    d0 = t0.getDay(),
    w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
    d1 = t1.getDay(),
    w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
  return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
    "H" + w0 * cellSize + "V" + 7 * cellSize +
    "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
    "H" + (w1 + 1) * cellSize + "V" + 0 +
    "H" + (w0 + 1) * cellSize + "Z";
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

看起来你忘了申报dateParse(并且使用它错了)。

var dateParse = d3.timeParse("%Y-%m-%d");

&#13;
&#13;
var width = 960,
  height = 136,
  cellSize = 17;

var color = d3.scaleQuantize()
  .domain([9000, 12000])
  .range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
var dateParse = d3.timeParse("%Y-%m-%d");
var svg = d3.select("body")
  .selectAll("svg")
  .data(d3.range(2017, 2018))
  .enter().append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

svg.append("text")
  .attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
  .attr("font-family", "sans-serif")
  .attr("font-size", 10)
  .attr("text-anchor", "middle")
  .text(function(d) {
    return d;
  });

var rect = svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#ccc")
  .selectAll("rect")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("rect")
  .attr("width", cellSize)
  .attr("height", cellSize)
  .attr("x", function(d) {
    return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
  })
  .attr("y", function(d) {
    return d.getDay() * cellSize;
  })
  .datum(d3.timeFormat("%Y-%m-%d"));

svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#000")
  .selectAll("path")
  .data(function(d) {
    return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("path")
  .attr("d", pathMonth);

d3.json("data3.json", function(error, data) {
  //populating data since i don't have the file
  data = [{
    "date": "2017-01-04",
    "open": 10430.69
  }, {
    "date": "2017-01-05",
    "open": 10584.56
  }];

  data.forEach(function(d) {
    d.dd = dateParse(d.date);
    console.log(d.dd);
  });

  var nest = d3.nest()
    .key(function(d) {
      return d.dd;
    })
    .map(data);

  rect.filter(function(d) {
      return d in data;
    })
    .attr("fill", function(d) {
      return color(data[d]);
    })
    .append("title")
    .text(function(d) {
      return d + ": " + data[d];
    });
});

function pathMonth(t0) {
  var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
    d0 = t0.getDay(),
    w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
    d1 = t1.getDay(),
    w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
  return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
    "H" + w0 * cellSize + "V" + 7 * cellSize +
    "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
    "H" + (w1 + 1) * cellSize + "V" + 0 +
    "H" + (w0 + 1) * cellSize + "Z";
}
&#13;
<script src="http://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;