Sorry, of course I don't really mean you're an idiot. I personally was always the type to turn down the "For Dummies" books when I was learning web technology years and years ago. My thinking was something along the lines that I am:
- Not a dummy
- Not a person that wants other people thinking I'm a dummy
- Not a person that wants a watered down version of something I'm passionate to learn about.
Hey Jerk, I'm not a dummy!
But then came along my immediate and burning need for a bar graph on my webpage. It was then I saw the light. Nowwwwwwww, I WANT to be a dummy. Why? Bar graphs are god awful boring. I didn't want to do it. I had a need to visualize some data, but the prospect of actually doing it sounded DUUUULLLLLLL.
Initially, I tried to get some free slave labor, but the only warm bodies in the room were either visually handicapped or just too lazy.
So I went over my options
- Draw the JSON loaded data in a canvas element
- Draw it using divs
- Kill me now
- Ohhhh wait....didn't I hear about this thing called D3.js?
Indeed I did hear about D3. I heard about it because while I was giving my Javascript Powered Kinect presentation at NCDevCon, a very smart gentleman in another room named Ben Clinkenbeard was giving a presentation on it.
Now, while I wasn't able to see the presentation, that was enough for me. I figured I'd give it a shot. But I had a severely bad attitude going in. "Grumble grumble bar graph"....."grumble grumble every other JS framework I've tried takes at least a few days to get up to speed with with".
OK fine....clear my mind, "I'm a dummy.....I'm a dummy. Copy a bunch of code from the samples and move on."
I found a decent sample after a short time looking: http://www.recursion.org/d3-for-mere-mortals/ I copied the bar graph code. And found it INCREDIBLY simple to run with it. It was easy to read and understand.
First, we'd need to create the d3 instance:
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h).attr("id", "myid");
Then, each element in the bar graph had a block of code with it. Like the actual bar itself:
svg.selectAll("rect").data(dataset).enter().append("rect")
.attr("x", function(d, i) {
return i * (w / dataset.length);
})
.attr("y", function(d) {
return h - (d * 4) - 20;
})
.attr("width", w / dataset.length - barPadding)
.attr("height", function(d) {
return d * 4;
})
.attr("fill", function(d) {
return "rgb(0, 0, 255)";
});
You can see here that we're creating (appending) a rectangle with a specific color at the specific x-axis position of the data (dataset). The height is the actual value of the data at the x-axis index.
Our copied example also put a numeric display of the count about the bar:
svg.selectAll("counttext")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return i * (w / dataset.length) + (w / dataset.length - barPadding) / 2;
})
.attr("y", function(d) {
return h - (d * 4) - 44;
})
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "black");
I then thought that, maybe I should put a date label below each bar to indicate how many hits on that day (the nature of what I wanted to show).
svg.selectAll("labeltext")
.data(labels)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return i * (w / dataset.length) + (w / dataset.length - barPadding) / 2;
})
.attr("y", function(d) {
return h;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "black");
You'll notice that to stick this text at the base along the x-axis - I make it set the "y" attribute to "h", the height of the entire display. And above, I made the "y" value of each bar "h-20", to give a 20 pixel buffer for text to show.
I added even more stuff too! The final result stacks a count of video hits and audio hits on a single bar, and displays each day for the past 30 days how many of each (and total hits) there are.
I also stacked the counts below the x-axis label, so I padded the bottom of the graph even more than my simple examples above.
You can see my results here: http://blastanova.com/play-trunk/dailyreports.html
Probably the hardest part was organizing the JSON data I wanted to drive the graph and slicing it a few different ways. As far as I could tell, each of your bar graph attributes need a one-dimensional array driving the attribute. it makes sense, but my situation in particular was a bit more complicated!
No problem though, it all worked out. And I got a bar graph and an education in D3.js in a night!
On a side note, it uses SVG (scalable vector graphics)! How cool is that! I noticed some blurriness on the sides of a few bars as it tried to anti-alias, but that's probably solvable (and maybe I shouldn't have overlaid my bars when I could've stacked them).
So right! My suggestion to you? Use what I write to inspire you to try out D3 and copy from better examples than mine. In the meantime, bar graphs don't suck anymore....I'm kinda interested to know more!