Varun's Weblog

Raphael JS Tutorial - Part I

Raphael.JS is a SVG/VML library which helps you to create quick vector shapes and images. Its very small and compact (only 86kb),easy to use,well documented and works in all browsers and yes even IE. Here is a list of all major browsers this library works on:

Chrome 5.0+ Firefox 3.0+, Safari 3.0+, Opera 9.5+ and Internet Explorer 6.0+

,finally its distributed under MIT license.

In this tutorial ,I intend to introduce basics of this library and help you get started.

Lets begin with some basic concepts. Raphael.JS uses the SVG W3C Recommendation and VML as a base for creating graphics, it hides quite a lot of technology specific nitty-gritties and instead present a unified api model . Here is a quick code sample

// Creates canvas 250 × 250 at 0, 0
var canvas = Raphael(0, 0, 250, 250 );
// Creates circle at x = 125, y = 125, with radius 50
var circle = canvas .circle(125, 125, 50);  
// Sets the fill attribute of the circle to red (#f00)
circle.attr("fill", "#f00");
// Sets the stroke attribute of the circle to white
circle.attr("stroke", "#fff");

The above code will create a circle in a middle of a canvas, here a canvas represent an HTML canvas element which is used as a drawing board with an id canvas. There is another way of binding your desired area with Raphael and that is by simply passing in the container element itself by using plain old document.getElementById("element").

var canvas = new Raphael(x, y, width, height); //first option 
var canvas = new Raphael(document.getElementById('element'), width, height); //second option  

Circle is one of the shape which can be drawn by using Raphael, others included in the  library are ellipse,rect ,path and finally image.

Here is a quick sample of drawing circle,ellipse and rectangle

// Creates canvas 250 × 250 at 0, 0
canvas = Raphael(0, 0, 250, 250 );
// Creates circle at x = 125, y = 125, with radius 50
var circle = canvas.circle(125, 125, 50);// Sets the fill attribute of the circle to red (#f00)
circle.attr("fill", "blue"); 
// Sets the stroke attribute of the circle to white
circle.attr("stroke", "#fff");
// Creates rectangle at x = 5, y = 5, with width and height = 50
var rectangle = canvas.rect(5, 5, 50, 50);  
rectangle.attr("fill", "green"); 
// Creates ellipse at x and y = 180 ,horizontal-axis = 20 and vertical-axis = 30
var ellipse = canvas.ellipse(180, 180, 20, 30); 
ellipse.attr("fill", "red"); 

Even though above mentioned are the most basic shapes which one might need, however it's the path element which actually gives us a true flexibility

We start a path by calling canvas.path("<instructions") method, where instructions are a sequence of directions we can give a path element along with the coordinates. The list of instructions can be found here.

Command Name Parameters
M moveto (x y)+
Z closepath (none)
L lineto (x y)+
H horizontal lineto x+
V vertical lineto y+
C curveto (x1 y1 x2 y2 x y)+
S smooth curveto (x2 y2 x y)+
Q quadratic Bézier curveto (x1 y1 x y)+
T smooth quadratic Bézier curveto (x y)+
A elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
R Catmull-Rom curveto* x1 y1 (x y)+

Here a simple diagonal line is created using path

// Creates canvas 250 × 250 at 0, 0
canvas = Raphael(0, 0, 250, 250 );
// draw a diagonal line:
// move to 10,10, line to 90,90
var path = canvas.path("M10 10 L 190 190");				
// Sets the stroke attribute of the path to red
path.attr("stroke", "red");
// Sets the stroke-width attribute of the path to 3.
path.attr("stroke-width", "3");

Path is extremly versatile and one could create other known shapes by using it. A simple circle can be created by using path for example

// Creates canvas 250 × 250 at 0, 0
canvas = Raphael(0, 0, 250, 250 );
// Creates circle shape using path at x = 125, y = 125, with radius 50
var circleDrawnasPath = canvas.path(getCircletoPath(125, 125, 50));
circleDrawnasPath.attr("stroke", "green");
circleDrawnasPath.attr("stroke-width", "3");

//Helper method to take x,y and r and return a path instruction string.
// x and y are center and r is the radius
function getCircletoPath(x , y, r)  {  return "M"+ x + "," + (y - r) + "A" + r + "," + r + ",0,1,1," + (x - 0.1) + "," + (y - r) +" z"; }

Paths can be used to create other intesting controls as well

			var canvas;
			window.onload = function () {
				// Creates canvas 250 × 300 at 0, 0
				canvas = Raphael(0, 0, 250, 270 );
				DrawBars(
				{
					"56%":56,
					"28%":28,
					"15%":15,
					"01%":1,
				} );
			};
			var DrawBars = function(data)
			{	 
				var vals = [];
				var labels = [];
				for(var key in data)
				{
					labels.push(key);
					vals.push(Number(data[key]));
				}
				var startingY = 55;
				var totalHeight = 60;
				var verticalGap = 8;
				var Height1 = Math.round(vals[0]/100*totalHeight);
				var Height2 = Math.round(vals[1]/100*totalHeight);
				var Height3 = Math.round(vals[2]/100*totalHeight);
				var Height4 = Math.round(vals[3]/100*totalHeight); 
				
				//Cube 4		 
				drawCube((startingY + Height1 + Height2 + Height3 + (verticalGap*3)),Height4,canvas,"#BBE6FB","#89D7f8","#39C8F4",labels[3]);
				//Cube 3		 
				drawCube((startingY + Height1 + Height2 + (verticalGap*2)),Height3,canvas,"#3FC8F4","#0CB5EB","#0094DA",labels[2]);
				//Cube 2		 
				drawCube((startingY + Height1 + (verticalGap*1)),Height2,canvas,"#2A80B8","#0269A6","#003F84","28% Android",labels[1]);
				//Cube 1		 
				drawCube(startingY,Height1,canvas,"#7F8184","#575759","#221E1F",labels[0]);
				
			}
			
			var drawCube = function(y,height,canvas,f1,f2,f3,label)
			{
				var rect1 = canvas.path("M 0 " + y + " 57 " + (y + 22) +" 188 " + y +" 127 " + (y - 16) + " 0 " + y);
				rect1.attr({fill: f1, stroke: f1, 'stroke-width': 0}); 
				
				var rect2 = canvas.path("M 0 " + y + " 0 " +(y + height) +" 57 " + (y + height + 22) + " 57 " + (y + 22) + " 0 " + y);				 
				rect2.attr({fill: f2, stroke: f2, 'stroke-width': 0}); 				 
				
				var rect3 = canvas.path("M 57 " + (y + 22) +" 57 " + (y + height + 22) +" 188 " + (y + height)+" 188 " + y +" 57 " + (y + 22));			 
				rect3.attr({fill: f3, stroke: f3, 'stroke-width': 0}); 
				var labely = y+height/2;
				var label1 = canvas.path("M 188 " + labely + " 226 " + labely)
				label1.attr({stroke: "#fff", 'stroke-width': 1}); 
				var text = canvas.text(226, labely, label);
				text.attr({"text-anchor":"start",'font-size':12,"font-family":"arial","fill":"#fff"});
				
				
			}

Rapael.js is a very versatile library, it suports many other feature like drawing images , text and animation. I intend to cover all that in future posts. Hope this helps.