Reputation: 3779
I have data that is an array of (date, start, stop)
tuples, where start and stop are minutes in the day [0, 1440]
, so 1 a.m. is represented as 60. I would like to plot rectangles, where each rectangle is horizontally aligned to the date and the height is the start and stop times. This is what I've got, which is close but has a couple errors (which errors are my question):
I want my rectangles to be as wide as a date column, but that's not quite what I'm seeing. In particular, my call to x_scale.rangeBand()
is giving me something wider than the column. (Note the horizontal overlap.) The - .5 * x_scale.rangeBand())
is meant to center the rectangles.
I'd like to indicate times rather than minutes on the y-axis, but the commented calls to Ticks()
and TickValues()
do not do it at all.
Pointers much appreciated.
This is the code that generates this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3.js"></script>
<style>
.d3-canvas { background-color: #F1EEFF; }
.icongray { fill: #5B5852; }
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script type="text/javascript">
var data = [{"date": new Date("2015-01-01"), "start": 0, "end": 60},
{"date": new Date("2015-01-02"), "start": 720, "end": 780},
{"date": new Date("2015-01-03"), "start": 1300, "end": 1440}]
var do_the_plot = function(width, height) {
margin = {"left": 45, "right": 25, "top": 25, "bottom": 25};
image_width = width - margin.left - margin.right;
image_height = height - margin.top - margin.bottom;
svg = setup_svg(width, height);
draw_it(svg);
}
log_int = function(label, the_int) {
console.log(label, the_int);
return the_int;
}
minutes_in_day = 1440;
// Set up an svg element for us. Return it.
setup_svg = function(width, height) {
num_days = 3
canvas = d3.select("body")
.append("svg")
.attr({"width": width,
"height": height,
"class": "d3-canvas",
});
inside = canvas.append("g")
.attr({"transform": "translate(" + margin.left + "," + margin.top + ")"
})
return inside;
}
// Draw some rectangles representing reading sessions.
draw_it = function(svg, reading_sessions) {
// Assume data is a list of {day, start, stop}, day an int
// (zero-based, days since start), start and stop minutes (int).
x_scale = d3.scale.ordinal()
//.domain([0, num_days])
.domain([new Date("2015-01-01"), new Date("2015-01-03")]) // Use from data.
.rangeRoundBands([0, image_width]);
y_scale = d3.scale.linear()
.domain([0, minutes_in_day])
.range([image_height, 0]);
h_scale = d3.scale.linear()
.domain([0, minutes_in_day])
.range([0, image_height]);
console.log("about to rect");
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr({
"width": function(d) { return log_int("w", x_scale.rangeBand()); },
"height": function(d) { return log_int("h", h_scale(d.end - d.start)); },
"x": function(d) { return log_int("x", x_scale(d.date) - .5 * x_scale.rangeBand()); },
"y": function(d) { return log_int("y", y_scale(d.end)); },
"class": "icongray"
});
console.log("got rects");
var x_axis = d3.svg.axis()
.scale(x_scale)
.orient("bottom")
.tickFormat(d3.time.format("%d-%m"));
svg.append("g")
.attr({"class": "axis",
"transform": "translate(0, " + image_height + ")",
})
.call(x_axis);
var y_axis = d3.svg.axis()
.scale(y_scale)
//.ticks([0, 180, 360, 540, 720, 900, 1080, 1260, 1440])
//.tickValues(["midnight", "3:00", "6:00", "9:00", "noon", "15:00", "18:00", "21:00", "midnight"])
.orient("left");
svg.append("g")
.attr({"class": "axis"})
.call(y_axis);
}
do_the_plot(300, 300);
</script>
</body>
</html>
Upvotes: 0
Views: 216
Reputation: 32327
.domain([new Date("2015-01-01"), new Date("2015-01-03")])
// should have been this.. it will give an array of all dates in data
.domain(data.map(function (d) {return d.date;}))
//y tick values
var y_values = [0, 180, 360, 540, 720, 900, 1080, 1260, 1440]
//y tick display for its corresponding values
var y_display = ["midnight", "3:00", "6:00", "9:00", "noon", "15:00", "18:00", "21:00", "midnight"]
.tickValues(y_values)
.tickFormat(function (d) {
var index = y_values.indexOf(d)
return y_display[index];
})
Full corrected code here: http://jsfiddle.net/cyril123/q4zy96zu/1/
Upvotes: 2