The Truematter team was recently tasked with creating a fun, sexy web app that presents numerical data in an engaging way. After putting our heads together, we came up with a bar chart that responds interactively to user input without, heaven forbid, reloading any pages. We’re very pleased to be able to share that with the coding community. There are some CSS tricks involved, a dose of jQuery, and some graphic magic, but when we’re done with this tutorial, we’ll have a beautifully interactive chart that you can customize to your heart’s content.
Prepping the Graphics
The graphic elements and the way those elements are chopped up and compiled is what really gives this chart some wow-factor. There are only three graphic elements needed for this project, but, since we’re essentially creating an illusion using CSS and images, those graphics need to be crafted with precision.
The chart itself is composed of three separate PNGs stacked on top of each other using CSS, two of which are stationary (the front and back “glassy” chart casing pieces), and one of which is animated using jQuery (the green bar piece in the middle).
Graphic Element 1: Back of the Chart
The background piece is comprised of the bottom of the chart (which we only see when the bar is empty at 0%), the back left and back right panels. On this bottommost layer, we include all of the faces of the graph casing that need to become “covered” when the graph is full or partially full. This is the layer that really gives the 3D illusion some depth.
Graphic Element 2: The Bar Graph
The animated center portion of this graph is simple to create. We suggest using very basic 3D extrude functions in Illustrator, or you can also just draw a three-panel shape in Photoshop and call it a day. Color your graph very brightly, oversaturating it as much as possible. Why? Because in the final chart, it will be shown beneath a semi-transparent casing, so the color will be muted by the layer that covers it.
It’s super important that the top and bottom edges of this piece remain transparent, so be sure to save it as a PNG.
Also just as important: make this piece exactly the same height as the graph casing pieces. In our pictures here, the middle layer looks shorter than the casing – when you create your central piece, make the central bar exactly as tall as the casing. If you make it too short, your graph will never be able to fill up to 100% properly. If you make it too tall, the graph can shoot out of the casing container when it’s animated.
Graphic Element 3: The Top Casing
Here’s where we get to the real visual trickery, which happens along the bottom edge of this third and final piece. While the top left and right edges retain transparency, the bottom left and right edges should be filled in solid with the same color as the background the graph will be sitting on.
For example, if your website background is black, the bottom two edges of this piece need to be filled in with solid black. In our example above, the site background is white, so we’ve filled in the bottom edges with white. This solid-color area effectively hides any overspill from the middle bar-chart piece (graphic element 2). Without this piece and its opaque bottom edge, we lose the 3D effect entirely. Here’s the graph without it:
The HTML
Okay! We’ve got all of our graphic pieces complete and we’re ready to jump right into the code. The HTML itself is pretty straightforward. You’re looking at a few basic form select fields and a few divs for the bar graph.
First, let’s look at the complete code, then we’ll take it piece by piece (no pun intended!). Note that the bar graph div elements are included within the form tag.
<noscript><h3>You must enable JavaScript to view this demo!</h3></noscript> <form id="form1" action="#" onsubmit="return false;"> <!-- container for the form elements --> <div id="formcontainer"> How much money do you want to contribute to savings each month? <select id="savings" onchange="calculate();"> <option selected="selected" value="0">- select an amount -</option> <option value="100">100 dollars</option> <option value="200">200 dollars</option> <option value="300">300 dollars</option> <option value="400">400 dollars</option> <option value="500">500 dollars</option> <option value="1000">1000 dollars</option> <option value="2000">2000 dollars</option> <option value="3000">3000 dollars</option> <option value="4000">4000 dollars</option> <option value="5000">5000 dollars</option> </select> What is your monthly income? <select id="income" onchange="calculate();"> <option selected="selected" value="0">- select an amount -</option> <option value="1000">1000 dollars</option> <option value="2000">2000 dollars</option> <option value="3000">3000 dollars</option> <option value="4000">4000 dollars</option> <option value="5000">5000 dollars</option> </select> </div> <div id="grapharea"> <h4>Percentage of Monthly Salary Saved</h4> <div id="p25">25%</div> <div id="p50">50%</div> <div id="p75">75%</div> <div id="p100">100%</div> <div id="graphcontainer"> <img id="graphbackground" src="http://nettuts.s3.amazonaws.com/2032_animatedBarGraph/images/graphbackground.png" alt="" width="262" height="430" /> <img id="graphbar" src="http://nettuts.s3.amazonaws.com/2032_animatedBarGraph/images/graphbar.png" alt="" width="262" height="430" /> <img id="graphforeground" src="http://nettuts.s3.amazonaws.com/2032_animatedBarGraph/images/graphforeground.png" alt="" width="262" height="430" /> </div> </div> </form>
The Breakdown
Since this chart depends on javascript, we first check to make sure it’s enabled in the browser:
<noscript><h3>You must enable JavaScript to view this demo!</h3></noscript>
Now we begin the form. For the purposes of this demo, we’ve used two simple dropdowns, but you could just as easily modify this code to use text fields, radio buttons, or any other type of input. The select onchange attribute is given the function “calculate();”, which we’ll cover in the jQuery section below.
<div id="formcontainer"> How much money do you want to contribute to savings each month? <select id="savings" onchange="calculate();"> <option selected="selected" value="0">- select an amount -</option> <option value="100">100 dollars</option> <option value="200">200 dollars</option> <option value="300">300 dollars</option> <option value="400">400 dollars</option> <option value="500">500 dollars</option> <option value="1000">1000 dollars</option> <option value="2000">2000 dollars</option> <option value="3000">3000 dollars</option> <option value="4000">4000 dollars</option> <option value="5000">5000 dollars</option> </select> What is your monthly income? <select id="income" onchange="calculate();"> <option selected="selected" value="0">- select an amount -</option> <option value="1000">1000 dollars</option> <option value="2000">2000 dollars</option> <option value="3000">3000 dollars</option> <option value="4000">4000 dollars</option> <option value="5000">5000 dollars</option> </select> </div>
And finally, included within the form tag, the graphic elements:
<div id="grapharea"> <h4>Percentage of Monthly Salary Saved</h4> <div id="p25">25%</div> <div id="p50">50%</div> <div id="p75">75%</div> <div id="p100">100%</div> <div id="graphcontainer"> <img id="graphbackground" src="http://nettuts.s3.amazonaws.com/2032_animatedBarGraph/images/graphbackground.png" alt="" width="262" height="430" /> <img id="graphbar" src="http://nettuts.s3.amazonaws.com/2032_animatedBarGraph/images/graphbar.png" alt="" width="262" height="430" /> <img id="graphforeground" src="http://nettuts.s3.amazonaws.com/2032_animatedBarGraph/images/graphforeground.png" alt="" width="262" height="430" /> </div> </div>
The CSS
#formcontainer { float: left; } #grapharea { position: relative; float: left; margin-left: 4em; } #graphcontainer { position: relative; width: 262px; height: 430px; overflow: hidden; } #graphbackground, #graphforeground { position: absolute; } #graphbar { position: absolute; top: 430px; } .graphlabel { position: absolute; left: 270px; } #p25 { top: 365px; } #p50 { top: 278px; } #p75 { top: 191px; } #p100 { top: 105px; }
Probably the most crucial thing that should catch your eye here is the #graphbar div. Notice that our #graphbar div starts out at 430px – the total height of the bar chart. This height declaration is the number that is manipulated via jQuery to make the graph animate. If you have created your own graphic elements which are taller or shorter than 430px, you’ll need to adjust that number to match your own graphics.
Likewise, you’ll also need to adjust the px of #p25, #p50, #p75, and #p100. These top declarations set the position of the 25%, 50%, 75% and 100% markers on the right side of the graph.
Also, take a close look at the #graphcontainer styles:
#graphcontainer { position: relative; width: 262px; height: 430px; overflow: hidden; }
Putting a position:relative;declaration on this outer wrapper lets us use absolute positioning on the three divs within #graphcontainer, so we can stack them on top of each other using CSS offsets. Setting a height and a width are also vital here – the height and width of this div should perfectly match the height and width of graphic elements 1 and 3. And overflow: hidden; hides the animated graphic, element 2, when it extends outside the bounds of the wrapping div.
The Code
Ah, now for the jQuery! It ties all pieces together and adds in the animation. A quick review of the full jQuery:
<script> function calculate() { var ZEROPOS = 355; var salary = $("#income").val(); var savings = $("#savings").val(); var percent = savings / salary; if (parseInt(savings) > 0 && parseInt(salary) > 0) { if (parseInt(savings) > parseInt(salary)) alert("You cannot save more than you earn - please change your selections accordingly."); else { val = (percent == 0) ? ZEROPOS : ZEROPOS - (percent * ZEROPOS); $("#graphbar").animate({ top: val + "px" }, 1500); } } } </script>
The Final Breakdown
First, create a constant to use in the calculations. ZEROPOS is the pixel value of where the central graphic element (graphic 2, the movable piece) should be positioned to represent 0%.
var ZEROPOS = 355;
Next, find the values selected by the user using the select boxes – salary and savings. Then calculate the percentage value – percent.
var salary = $("#income").val(); var savings = $("#savings").val(); var percent = savings / salary;
The next step is a validation check to make sure the user has actually selected values from both select boxes. If they have, we continue with the script. Otherwise, we do nothing.
if (parseInt(savings) > 0 && parseInt(salary) > 0)
If the user has entered the appropriate values, we then make sure that they have selected a salary that is higher than the amount they want to contribute to savings. If they have, we continue with the script. Otherwise we prompt the user to change their selections.
if (parseInt(savings) > parseInt(salary)) alert("You cannot save more than you earn - please change your selections accordingly.");
Now we are finally to the meat of the script – calculating the position to which we will move the graph bar and then firing off the jQuery animate functionality to make it happen.
val = (percent == 0) ? ZEROPOS : ZEROPOS - (percent * ZEROPOS); $("#graphbar").animate({ top: val + "px" }, 1500);
So, in calculating the value for the graph bar position – val – first determine if the percentage is zero. If so, set value equal to the ZEROPOS constant. Otherwise, calculate the new bar position by subtracting the percentage value multiplied by the zero position value from the zero position value. This formula is used because we are animating the bar from the zero position at the bottom of the chart up towards the top.
Once the pixel value is calculated, we know where we’re heading, so simply call the animate method in jQuery on the graphbar object passing in the new CSS value for the top position with an animation rate of 1500 (the speed of the animation in milliseconds). Then jQuery does the magic for us and moves the bar within the chart accordingly. Violà!
Hope you enjoyed this tutorial!
Comments