live streaming plot that accumulates - d3.js

I am totally new to D3 and trying to make a live streaming plot similar to the third one found here.
The difference, however, is that I need the data to accumulate/build up rather than pass by. I have tried to replicate the code from here and simply commented out the part where they translate and pop off old data, but that still doesn't do it.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var n = 40,
random = d3.random.normal(0, .2),
data = d3.range(n).map(random);
var margin = {top: 20, right: 20, bottom: 20, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([1, n - 2])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 1])
.range([height, 0]);
var line = d3.svg.line()
.interpolate("basis")
.x(function(d, i) { return x(i); })
.y(function(d, i) { return y(d); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
tick();
function tick() {
// push a new data point onto the back
data.push(random());
// redraw the line, but don't slide it to the left
path
.attr("d", line)
.attr("transform", null)
.transition()
.duration(500)
.ease("linear")
//.attr("transform", "translate(" + x(0) + ",0)")
.each("end", tick);
// don't pop the old data point off the front
// data.shift();
}
</script>

Inside your tick function you need to add these lines:
data.push(random());//generate the random points
x.domain([1, data.length - 2])//update the x axis domain
xaxis.call(d3.svg.axis().scale(x).orient("bottom"))//redraw the x axis
working code here

Related

String x ticks not scaling data in D3

`
var margin = {top: 50, right: 50, bottom: 50, left: 50}
, width = window.innerWidth - margin.left - margin.right
, height = window.innerHeight - margin.top - margin.bottom;
// n data points
var n = 7;
// X scale
var xScale = d3.scaleBand()
.domain(['A','B','C','D','F','E','Z']) // input
.range([0, width]); // output
// Y scale
var yScale = d3.scaleLinear()
.domain([0, 1])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d.y); })
.curve(d3.curveMonotoneX)
var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)()} })
// SVGs
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "white");
svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x axis call
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
// y axis call
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
// 12. Appends a circle for each datapoint
svg.selectAll(".dot")
.data(dataset)
.enter().append("circle") // Uses the enter().append() method
.attr("class", "dot") // Assign a class for styling
.attr("cx", function(d, i) { return xScale(i) })
.attr("cy", function(d) { return yScale(d.y) })
.attr("r", 6);
svg.append("text")
.attr("class", "title")
.attr("x", width/2)
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.text("Testing");
/* 13. Basic Styling with CSS */
/* Style the lines by removing the fill and applying a stroke */
.line {
fill: none;
stroke: green;
stroke-width: 3;
}
/* Style the dots by assigning a fill and stroke */
.dot {
fill: red;
stroke: #fff;
}
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
</style>
<!-- Body tag is where we will append our SVG and SVG objects-->
<body>
</body>
<!-- Load in the d3 library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
</script>
I need for each data point to correspond to an (string) x-coordinate.
I am knew to d3 and I have yet to get accustomed to formatting axis.
I would also be great if anyone can point me out to how to add a tooltip. (Just an explanation)
Thank you everyone.
Not sure why it keeps saying your: "
It looks like your post is mostly code; please add some more details."
`
The scaleOrdinal is mapped to an array of alphabets but when you are calculating the cx you are mapping to an integer i. To resolve this:
Separate the labels as as array first:
var labels = ['A','B','C','D','F','E','Z'];
Then pass the labels to the domain:
// X scale
var xScale = d3.scaleBand()
.domain(labels) // input
.range([0, width]); // output
Finally, when you call calculate the cx, you need to send a value which was used in the domain. In your case since your domain is an array of alphabets you need to reparse the i to that particular alphabet. Hence you need to return xScale(labels[i]) as below:
svg.selectAll(".dot")
.data(dataset)
.enter().append("circle") // Uses the enter().append() method
.attr("class", "dot") // Assign a class for styling
.attr("cx", function(d, i) { return xScale(labels[i]) })
.attr("cy", function(d) { return yScale(d.y) })
.attr("r", 6);
Full working snippet below. Hope this helps.
var margin = {top: 50, right: 50, bottom: 50, left: 50}
, width = window.innerWidth - margin.left - margin.right
, height = window.innerHeight - margin.top - margin.bottom;
// n data points
var n = 7;
//labels
var labels = ['A','B','C','D','F','E','Z'];
// X scale
var xScale = d3.scaleBand()
.domain(labels) // input
.range([0, width]); // output
// Y scale
var yScale = d3.scaleLinear()
.domain([0, 1])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d.y); })
.curve(d3.curveMonotoneX)
var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)()} })
// SVGs
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "white");
svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x axis call
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
// y axis call
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
// 12. Appends a circle for each datapoint
svg.selectAll(".dot")
.data(dataset)
.enter().append("circle") // Uses the enter().append() method
.attr("class", "dot") // Assign a class for styling
.attr("cx", function(d, i) { return xScale(labels[i]) })
.attr("cy", function(d) { return yScale(d.y) })
.attr("r", 6);
svg.append("text")
.attr("class", "title")
.attr("x", width/2)
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.text("Testing");
/* 13. Basic Styling with CSS */
/* Style the lines by removing the fill and applying a stroke */
.line {
fill: none;
stroke: green;
stroke-width: 3;
}
/* Style the dots by assigning a fill and stroke */
.dot {
fill: red;
stroke: #fff;
}
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
</style>
<!-- Body tag is where we will append our SVG and SVG objects-->
<body>
</body>
<!-- Load in the d3 library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
</script>
Updated Snippet with Lines:
var margin = {top: 50, right: 50, bottom: 50, left: 50}
, width = window.innerWidth - margin.left - margin.right
, height = window.innerHeight - margin.top - margin.bottom;
// n data points
var n = 7;
//labels
var labels = ['A','B','C','D','F','E','Z'];
// X scale
var xScale = d3.scaleBand()
.domain(labels) // input
.range([0, width]); // output
// Y scale
var yScale = d3.scaleLinear()
.domain([0, 1])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) { return xScale(labels[i]); })
.y(function(d) { return yScale(d.y); })
.curve(d3.curveMonotoneX)
var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)()} })
// SVGs
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "white");
svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x axis call
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
// y axis call
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
// 12. Appends a circle for each datapoint
svg.selectAll(".dot")
.data(dataset)
.enter().append("circle") // Uses the enter().append() method
.attr("class", "dot") // Assign a class for styling
.attr("cx", function(d, i) { return xScale(labels[i]) })
.attr("cy", function(d) { return yScale(d.y) })
.attr("r", 6);
svg.append("text")
.attr("class", "title")
.attr("x", width/2)
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.text("Testing");
/* 13. Basic Styling with CSS */
/* Style the lines by removing the fill and applying a stroke */
.line {
fill: none;
stroke: green;
stroke-width: 3;
}
/* Style the dots by assigning a fill and stroke */
.dot {
fill: red;
stroke: #fff;
}
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
</style>
<!-- Body tag is where we will append our SVG and SVG objects-->
<body>
</body>
<!-- Load in the d3 library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
</script>

d3 version 4 path line smooth transition with Mike Bostock's example

My first time to post question here. I am converting my version 3 of d3 path line transition code to version 4, and I am having a hard time.
First of all, I saw Mike's example (posted about two days agao) of smooth line transition with non-time x axis for version 4, so I did the similar thing to his example of version 3 with time x axis. The path line moves smoothly, but the x axis doesn't. Also, for my work, I cannot trigger the transition from where he did in this example, so I cannot use the variable "this" in the tick function. Here is the code:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="//d3js.org/d3.v4.min.js"></script>
<style>
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
(function() {
var n = 243,
duration = 750,
now = new Date(Date.now() - duration),
count = 0,
data = d3.range(n).map(function() { return 0; });
random = d3.randomNormal(0, .2),
data = d3.range(n).map(random);
var margin = {top: 6, right: 0, bottom: 20, left: 40},
width = 960 - margin.right,
height = 120 - margin.top - margin.bottom;
var x = d3.scaleTime()
.domain([now - (n - 2) * duration, now - duration])
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var line = d3.line()
.x(function(d, i) { return x(now - (n - 1 - i) * duration); })
.y(function(d, i) { return y(d); });
var svg = d3.select("body").append("p").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", -margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var axis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(x.axis = d3.axisBottom().scale(x));
var timeline = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.datum(data)
.attr("class", "line")
.transition()
.duration(500)
.ease(d3.easeLinear)
.on("start", tick);
var transition = d3.select({}).transition()
.duration(750)
.ease(d3.easeLinear);
function tick() {
data.push(random());
now = new Date();
x.domain([now - (n - 2) * duration, now - duration]);
y.domain([0, d3.max(data)]);
// redraw the line
svg.select(".line")
.attr("d", line)
.attr("transform", null);
// slide the x-axis left
axis.call(x.axis);
// slide the line left
d3.active(this)
.attr("transform", "translate(" + x(now - (n - 1) * duration) + ")")
.transition().on("start", tick);
// pop the old data point off the front
data.shift();
}
})()
</script>
</body>
at the tick function, there is a "this", from debugging, I found out it's a path, so I tried to replace it with d3.active(d3.selectAll("path")), or d3.active(d3.selectAll(".line")), neither works. I also tried to assign a variable timeline to the path, so that I tried d3.active(timeline). It doesn't work either.
I am at my wits' end on this issue. I posted on d3 google group, nobody answered. I hope somebody here can give me some suggestions.
Thanks
Diana
The transition to v4 is indeed not easy. Had the same issue as you. Try the following code:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="//d3js.org/d3.v4.min.js"></script>
<style>
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
(function() {
var n = 243,
duration = 750,
now = new Date(Date.now() - duration),
count = 0,
data = d3.range(n).map(function() {
return 0;
});
random = d3.randomNormal(0, .2),
data = d3.range(n).map(random);
var margin = {top: 6, right: 0, bottom: 20, left: 40},
width = 960 - margin.right,
height = 120 - margin.top - margin.bottom;
var x = d3.scaleTime()
.domain([now - (n - 2) * duration, now - duration])
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var line = d3.line()
.x(function(d, i) {
return x(now - (n - 1 - i) * duration);
})
.y(function(d, i) {
return y(d);
});
var svg = d3.select("body").append("p").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", -margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var axis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(x.axis = d3.axisBottom().scale(x));
var timeline = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.datum(data)
.attr("class", "line")
.transition()
.duration(500)
.ease(d3.easeLinear);
var transition = d3.select({}).transition()
.duration(750)
.ease(d3.easeLinear);
(function tick() {
transition = transition.each(function() {
data.push(random());
now = new Date();
x.domain([now - (n - 2) * duration, now - duration]);
y.domain([0, d3.max(data)]);
// redraw the line
svg.select(".line")
.attr("d", line)
.attr("transform", null);
// slide the x-axis left
axis.call(d3.axisBottom(x));
// slide the line left
//d3.active(this).attr("transform", "translate(" + x(now - (n - 1) * duration) + ")");
// pop the old data point off the front
data.shift();
}).transition().on("start", tick);
})();
})()
</script>
</body>
The trick is to chain transitions and using transition().on rather than transition().each. To update the axis you need to call the d3.axisBottom(x) in the same way that you instantiate the axis.

Styling Axis Data in D3.js

I have this piece of code which fetches data from MySQL and plots the graph, and it does it correctly. However, the marking segments such as the time span coming up in text appears to be in black. I've tried doing many changes but it was futile. I want to make it white.
Also, I want the x-axis to start with January and not 2015 as seen in the image.
<style>
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 900 - margin.left - margin.right,
height = 540 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%Y-%m-%d").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.lsdate); })
.y(function(d) { return y(d.units); });
// Adds the svg canvas
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.json("common/scripts/charts.php", function(error, data) {
data.forEach(function(d) {
d.lsdate = parseDate(d.lsdate);
d.units = +d.units;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.lsdate; }));
y.domain([0, d3.max(data, function(d) { return d.units; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
Screenshot:
As per #Lars's comment, you need to use the fill attribute to apply style to your text elements:
.axis text {
fill: white;
}
Working fiddle here: http://jsfiddle.net/henbox/jr6pk4bj/1/
Aside: To prevent the x-axis starting with the year, but to always use month names, add this line when you define xAxis:
.tickFormat(d3.time.format("%B"));
Here's an update to the fiddle showing that change too: http://jsfiddle.net/henbox/jr6pk4bj/2/

TypeError: string is undefined (var c, p, i = 0, n = template.length, m = string.length;)

I am starting with this simple example but I have the following error (using Firebug)
TypeError: string is undefined
[Break On This Error]
var c, p, i = 0, n = template.length, m = string.length;
Any hint?? (I tried similar responses and it didn't work, I guess there is something wrong with the time and date format, but I believe the "%Y-%m-%d" format is the right one that I have in the csv file...)
Thanks!!
//here my prueba.html file
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body{font: 12px arial;}
path{stroke: steelblue;
stroke-width: 2;
fill: none;}
.axis path,
.axis line {fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;}
</style>
<body>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<script>
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse; // HERE ERROR !!!
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var valueline = d3.svg.line()
.x(function(d) { return x(d.timestamp); })
.y(function(d) { return y(d.temperature); });
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top +")");
// Get the data
d3.tsv("data/data.csv", function(error, data)
{data.forEach(function(d)
{d.timestamp = parseDate(d.timestamp); // HERE ERROR !!!
d.temperature = +d.temperature;});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
svg.append("path") // Add the valueline path.
.attr("d", valueline(data));
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
});
</script>
</body>
//here my data.csv file
timestamp,temperature
1900-01-01,20
1900-01-02,20
1900-01-03,17
1900-01-04,23
1900-01-05,15
1900-01-06,22
1900-01-07,24
1900-01-08,15
1900-01-09,25
1900-01-10,19
1900-01-11,23
1900-01-12,19
1900-01-13,17
1900-01-14,15
1900-01-15,17
1900-01-16,21
1900-01-17,23
1900-01-18,25
1900-01-19,17
1900-01-20,22
1900-01-21,23
1900-01-22,17
1900-01-23,15
1900-01-24,23
1900-01-25,19
1900-01-26,25
1900-01-27,21
1900-01-28,22
1900-01-29,20
1900-01-30,15
1900-01-31,21
1900-02-01,19
1900-02-02,15
1900-02-03,15
1900-02-04,25
1900-02-05,23
1900-02-06,25
1900-02-07,15
1900-02-08,18
1900-02-09,22
1900-02-10,15
1900-02-11,19
1900-02-12,18
1900-02-13,24
1900-02-14,22
1900-02-15,16
1900-02-16,21
1900-02-17,24
1900-02-18,25
A picture of this using Chrome developer tools...
http://i.imgur.com/0vZhCgK.jpg?1
You are using d3.tsv, you should be using d3.csv instead.
Also if you want to use tsv (Tab-separated values) you'll need to replace every comas by a tabulation.
PS: care to not save the file with an editor that automatically replace the tabulations with spaces :)

D3 Parsing Error

This is likely a very easy question (but I'm new to D3 and trying to go through some of the examples to get a better understanding of how it works). I'm trying to modify one of the base examples for D3 (http://bl.ocks.org/mbostock/1667367). I've basically kept everything the same... I'm just trying to use a different csv file with my own data (vs. the S&P 500 stock data). In the example file, the csv file has a date (month year) and a stock price. In my data, I have a UTC time stamp and a light value (between 0-1000). Here's a small example of the csv:
date, light
2013-01-01T09:00:00.000Z,554.22
2013-01-01T09:01:00.000Z,480.83
2013-01-01T09:02:00.000Z,433.19
2013-01-01T09:03:00.000Z,596.89
2013-01-01T09:04:00.000Z,421.78
2013-01-01T09:05:00.000Z,461.23
2013-01-01T09:06:00.000Z,560.04
When, I run my code I get an error in the console window saying I have a parsing error (not sure if it's getting caught up in parsing the data or the light value)... Does anyone see a problem with how I'm setting up the csv file (or how I might be parsing it incorrectly)? Here's the D3 code I'm working with.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
path {
fill: steelblue;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 10, right: 10, bottom: 100, left: 40},
margin2 = {top: 430, right: 10, bottom: 20, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brush);
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.light); });
var area2 = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x2(d.date); })
.y0(height2)
.y1(function(d) { return y2(d.light); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.csv("Light.csv", function(error, data) {
console.log(data);
data.forEach(function(d) {
d.date = parseDate(d.date);
//d.light = +d.light;
//console.log(d);
});
x.domain(d3.extent(data.map(function(d) { return d.date; })));
y.domain([0, d3.max(data.map(function(d) { return d.light; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("clip-path", "url(#clip)")
.attr("d", area);
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
context.append("path")
.datum(data)
.attr("d", area2);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
});
function brush() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
}
</script>
In the header of your csv file, the "light" header has an extra space in front of it. That leads to processing problems with d3.csv.
data.forEach(function(d) {
d.date = parseDate(d.date);
d.light = +d.light; // won't be able to access the light column data with the space
d.light = d[' light']; // this would work if you can't fix the header at the csv source
});
Hmmm, maybe I'll submit a patch to d3 to fix this...
You are probably getting that error because of your time format specification -- there is no %L placeholder (see the documentation). This should work.
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.000Z").parse;

Resources