Line chart with x-axis as dates

143 views
Skip to first unread message

bannerlog

unread,
Apr 15, 2010, 8:05:30 PM4/15/10
to protovis
I read the documentation and this group. Still don't understood how to
create a linear scale for chart with x-axis as date line.

It's easy to do like in example (scales for canvas size):
var x = pv.Scale.linear(points, function(d) d.x).range(0, width);

How to create pv.Rule with dates?
For example I have an array of 4 points (each {x,y}) and an array with
4 dates. After scale (as shown above) it makes 7 ticks.

--
You received this message because you are subscribed to the Google Groups "protovis" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protovis+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protovis?hl=en.

Chris Diehl

unread,
Apr 16, 2010, 4:27:10 PM4/16/10
to protovis
I needed to solve this problem recently for a timeline viz. I wrote
the following routine that you may be able to just use straightaway to
address your problem. Hope this helps. Chris

/*
* pvTimelineVis
*
* syntax:
* inputs:
* panelWidth: width of the root panel
* panelHeight: height of the root panel
* minDT: starting datetime for the timeline
* maxDT: ending datetime for the timeline
* countArrays: array of arrays containing counts for each event
class
* maxEvents: maximum number of events occurring in a given time
interval
*
*/

function pvTimelineVis(panelWidth, panelHeight, minDT, maxDT,
countArrays, maxEvents) {

var numBins = countArrays[0].length, // number of time
intervals
numClasses = countArrays.length; // number of event
classes
tlDim = Math.min( panelHeight * 0.9,
panelWidth * 0.8 ), // width/height of the
timeline
xBufferDim = panelWidth * 0.1, // buffer left of the timeline
yBufferDim = panelHeight * 0.1; // buffer below the timeline

// mappings from data to pixels for x and y axes
var x = pv.Scale.ordinal(pv.range(numBins)).splitBanded(0, tlDim),
y = pv.Scale.linear(0, maxEvents).range(0, tlDim);

// create the root panel for the timeline visualization
var vis = new pv.Panel()
.width(tlDim + (2 * xBufferDim))
.height(tlDim + yBufferDim);

// add the horizontal reference lines
vis.add(pv.Rule)
.data(y.ticks())
.bottom(function(d) { return y(d) + yBufferDim })
.left(xBufferDim)
.width(tlDim)
.strokeStyle("rgba(255,255,255,.3)");

// add the y axis tick marks and numeric labels
vis.add(pv.Rule)
.data(y.ticks())
.bottom(function(d) { return y(d) + yBufferDim })
.left(xBufferDim - 5)
.width(5)
.strokeStyle("rgba(255,255,255,1)")
.anchor("left").add(pv.Label)
.textStyle("white");

// compute the time in milliseconds of the start of the first whole
day
// and the number of date labels to display on the x axis
var SECS_PER_DAY = 86400000,
dt = new Date(minDT.getFullYear(), minDT.getMonth(),
minDT.getDate(), 0, 0, 0, 0),
beginSec = dt.getTime() + SECS_PER_DAY,
numDays = Math.ceil((maxSec - beginSec) / SECS_PER_DAY);

// add the vertical reference lines
vis.add(pv.Rule)
.data(pv.range(0,numDays,1).map(function(d) { return beginSec + d *
SECS_PER_DAY }))
.bottom(yBufferDim)
.left(function(d) { return x(Math.floor((d - minSec) / binWidth)) +
xBufferDim })
.strokeStyle("rgba(255,255,255,.3)");

// add the x axis tick marks and date labels
vis.add(pv.Rule)
.data(pv.range(0,numDays,1).map(function(d) { return beginSec + d *
SECS_PER_DAY }))
.bottom(yBufferDim - 5)
.left(function(d) { return x(Math.floor((d - minSec) / binWidth)) +
xBufferDim })
.height(5)
.strokeStyle("rgba(255,255,255,1)")
.anchor("bottom").add(pv.Label)
.text(function(s) { d = new Date(s); return d.format("%m/%d/%y") })
.textStyle("white");

// add the stacked area chart to the visualization
vis.add(pv.Panel)
.bottom(yBufferDim)
.height(tlDim)
.data(countArrays)
.add(pv.Area)
.data(function(d) { return d })
.bottom(pv.Layout.stack())
// .width(tlDim / numBins) // for stacked bar (pv.Bar)
chart
.height(y)
.left(function() { return x(this.index) + xBufferDim });

return vis;

Mike Bostock

unread,
Apr 16, 2010, 5:23:06 PM4/16/10
to prot...@googlegroups.com
> I read the documentation and this group. Still don't understood how to
> create a linear scale for chart with x-axis as date line.

You don't need to do anything "special" for dates; treat dates like
numbers, and quantitative scales will do the right thing.*
(Internally, the dates are automatically converted to numbers
representing milliseconds since UNIX epoch.)

So in your code, say that `d.x` refers to a Date, rather than a
number. Similarly, you can create a rule with dates by specifying the
data property as an array of dates, and then passing those dates to
the scale to position the rule. For example:

http://graphics.stanford.edu/~mbostock/dates/dates.html

Mike

* There was a bug related to this in 3.1, that was fixed for 3.2. See:
http://gitorious.org/protovis/protovis/commit/16ad10412f624ce36666823b90169ea6cb853e31

bannerlog

unread,
Apr 17, 2010, 6:57:04 AM4/17/10
to protovis
Thanks Mike.
Reply all
Reply to author
Forward
0 new messages