Raphael - Documentation

What is Raphael.js?

Raphael.js is a small JavaScript library that allows you to create vector graphics on the fly in any browser that supports SVG, VML, or Canvas. It provides a simple and consistent interface for creating and manipulating various vector shapes, including paths, ellipses, rectangles, text, and images. This simplifies the process of adding interactive and dynamic vector graphics to your web applications without the complexities of directly working with SVG or other vector formats. Raphael.js handles the browser-specific rendering details, allowing you to focus on the design and functionality of your graphics.

Setting up Raphael.js

Raphael.js can be included in your project in a few ways:

Once included, you can use the Raphael object in your JavaScript code.

Browser Compatibility

Raphael.js aims for broad browser compatibility. While it primarily leverages SVG for rendering, it falls back to VML for older Internet Explorer versions and Canvas as a last resort. However, for optimal performance and feature support, using modern browsers with SVG support is recommended. Consult the official Raphael.js documentation or release notes for the most up-to-date browser compatibility information.

Basic Example

This example creates a simple red circle with a radius of 50 pixels at position (50,50) on the page:

// Create a canvas that's 300 pixels wide by 200 pixels tall
var paper = Raphael("canvas", 300, 200); // Replace "canvas" with your canvas element ID

// Create a circle shape
var circle = paper.circle(50, 50, 50);

// Set the circle's fill color to red
circle.attr({fill: "red"});

Remember to include the Raphael.js library and create a <div> element with the ID “canvas” in your HTML file:

<!DOCTYPE html>
<html>
<head>
<title>Raphael.js Example</title>
</head>
<body>
<div id="canvas"></div>
<script src="raphael.min.js"></script>  <!-- Or CDN link -->
<script>
  // JavaScript code from the example above goes here
</script>
</body>
</html>
```  This will display a red circle on your page.  This basic example provides a starting point for exploring the numerous functionalities offered by Raphael.js.


## Creating Shapes

### Creating Circles

Raphael.js provides the `circle()` method to create circles.  It takes three arguments: the x-coordinate of the center, the y-coordinate of the center, and the radius.  The returned object is a Raphael element representing the circle, which can be further manipulated using attribute methods.

```javascript
// Create a paper object (replace "canvas" with your canvas element ID)
var paper = Raphael("canvas", 500, 300);

// Create a circle with center at (50, 50) and radius 25
var myCircle = paper.circle(50, 50, 25);

// Set attributes (optional):
myCircle.attr({
  fill: "blue",       // Fill color
  stroke: "red",     // Stroke color
  "stroke-width": 3   // Stroke width
});

Creating Rectangles

The rect() method creates rectangles. It takes four arguments: the x-coordinate of the top-left corner, the y-coordinate of the top-left corner, the width, and the height.

// Create a rectangle with top-left corner at (150, 50), width 100, height 50
var myRect = paper.rect(150, 50, 100, 50);
myRect.attr({
  fill: "green",
  stroke: "black",
  "stroke-width": 2
});

Creating Ellipses

Ellipses are created using the ellipse() method. It requires four arguments: the x-coordinate of the center, the y-coordinate of the center, the radius on the x-axis, and the radius on the y-axis.

// Create an ellipse with center at (300, 50), x-radius 50, y-radius 25
var myEllipse = paper.ellipse(300, 50, 50, 25);
myEllipse.attr({
  fill: "yellow",
  stroke: "purple",
  "stroke-width": 1
});

Creating Paths

Paths offer the most flexibility for creating complex shapes. The path() method accepts a string describing the path using SVG path syntax. This syntax uses commands like M (moveto), L (lineto), C (curveto), Z (closepath), etc.

// Create a star shape using path commands
var myPath = paper.path("M100,150 L120,100 L180,100 L200,150 L160,190 L120,190 Z");
myPath.attr({fill: "orange"});

Creating Images

Raphael.js allows you to add images to the canvas using the image() method. It requires five arguments: the URL of the image, the x-coordinate, the y-coordinate, the width, and the height.

// Add an image (replace with your image URL)
var myImage = paper.image("myimage.jpg", 200, 150, 50, 50);

Creating Text

The text() method creates text elements. It accepts three arguments: the x-coordinate, the y-coordinate, and the text string.

// Add text at (100, 250)
var myText = paper.text(100, 250, "Hello, Raphael!");
myText.attr({
  "font-size": 20,
  "font-family": "Arial",
  "fill": "black"
});

Remember that in all these examples, you need to have a Raphael paper object created first, typically by using Raphael(containerID, width, height), where containerID is the ID of a <div> or other suitable HTML element. The width and height values specify the dimensions of the drawing canvas.

Manipulating Shapes

Translation

Translation moves a shape along the x and y axes. Raphael.js uses the translate() method for this. It takes two arguments: the horizontal displacement (dx) and the vertical displacement (dy).

var paper = Raphael("canvas", 500, 300);
var rect = paper.rect(50, 50, 100, 50);

// Translate the rectangle 50 pixels to the right and 20 pixels down
rect.translate(50, 20);

Scaling

Scaling changes the size of a shape. The scale() method takes two arguments: the horizontal scaling factor (sx) and the vertical scaling factor (sy). A value of 1 means no scaling, values greater than 1 enlarge the shape, and values less than 1 reduce its size. An optional third argument specifies the x and y coordinates of the scaling center (defaults to the shape’s center).

var circle = paper.circle(150, 150, 30);
// Scale the circle to twice its size, centered at its current center.
circle.scale(2, 2);

// Scale the circle to half its size, with the scaling origin at 200,150.
circle.scale(0.5, 0.5, 200,150);

Rotation

Rotation turns a shape around a given point. The rotate() method takes one argument: the angle of rotation in degrees (clockwise). An optional second and third argument specify the x and y coordinates of the rotation center (defaults to the shape’s center).

var ellipse = paper.ellipse(300, 150, 40, 20);
// Rotate the ellipse 45 degrees counter-clockwise around its center
ellipse.rotate(45);

//Rotate the ellipse 30 degrees clockwise around the point (350, 180)
ellipse.rotate(-30, 350, 180);

Transformations

Raphael.js also provides a transform() method that allows combining multiple transformations (translate, scale, rotate) using a single string. The string uses a space-separated list of transformations in the form [command][x][y][z], where the command is t for translate, s for scale, r for rotate, and m for matrix transformation.

var path = paper.path("M10,10 L100,100");

// Apply multiple transformations: translate, then rotate
path.transform("t10,20r30");

//Applying matrix transform.  Note that matrix transformation requires 6 arguments.
path.transform("m1,0,0,1,10,10"); //This translates the path 10 pixels to the right and 10 pixels down.

Attributes

Attributes control various aspects of a shape’s appearance, such as fill color, stroke color, stroke width, opacity, etc. These are set using the attr() method. You can set multiple attributes at once using an object as an argument.

var square = paper.rect(10, 10, 40, 40);

//Set attributes
square.attr({
    "fill": "#f00", //red fill
    "stroke": "#000", //black stroke
    "stroke-width": 5,
    "opacity": 0.5
});

//Get a specific attribute
let fillColor = square.attr("fill"); //Gets the fill color
console.log(fillColor);

Animation

Raphael.js provides powerful animation capabilities using the animate() method. This method allows you to smoothly change a shape’s attributes over time. It takes two arguments: an object containing the target attribute values and the animation duration in milliseconds. An optional third argument specifies an easing function (e.g., ‘>’, ‘<’, ‘<>’, ‘backIn’, etc.).

var circle = paper.circle(100, 100, 20);

// Animate the circle to a new position and size over 1000 milliseconds
circle.animate({cx: 200, cy: 200, r: 40}, 1000, ">");


// Example with a callback function:
circle.animate({cx: 100, cy: 100, r: 20}, 1000, function(){
    console.log("Animation complete!");
});

Remember to consult the Raphael.js documentation for a complete list of attributes and easing functions available. The animate function allows chaining animations but subsequent animations overwrite previous animations. To queue animations, use the animateWith function instead.

Working with Paths

Path String Syntax

Paths in Raphael.js are defined using a string following the SVG path syntax. This string consists of a series of commands and their corresponding coordinates. Each command is a single letter, followed by numerical parameters separated by commas.

Here are some common commands:

Commands are case-insensitive, but it’s best practice to use uppercase for consistency. Multiple commands can be chained together in a single string. For example: "M10 10 L 100 100 L 100 200 Z" creates a closed right-angled triangle.

Path Manipulation

Once a path is created using paper.path(pathString), you can manipulate it in several ways:

Creating Complex Shapes with Paths

Paths are essential for creating complex shapes that cannot be easily represented with simple primitives like rectangles or circles. By combining various commands, you can generate intricate designs.

var paper = Raphael("canvas", 500, 300);

// Example: Creating a star shape
var star = paper.path("M150,100 L180,160 L240,160 L180,220 L210,280 L150,230 L90,280 L120,220 L60,160 L120,160 Z");
star.attr({fill: "gold"});


//Example: Creating a curved shape
var curvedShape = paper.path("M 50,50 C 50,150 200,150 200,50 L 200,100 C 200, 200, 100,200, 100,100 L100,50 Z");
curvedShape.attr({fill: "lightblue", stroke: "darkblue"});

Remember that complex paths can become difficult to manage manually. Consider using tools or libraries that help you generate SVG path strings for more intricate shapes if needed. The examples above illustrate the power and flexibility of paths in constructing diverse and elaborate vector graphics.

Color and Styles

Fill and Stroke

In Raphael.js, the fill attribute determines the color or pattern used to fill a shape’s interior, while the stroke attribute sets the color and style of the shape’s outline (border). Both are specified using the attr() method. If fill is omitted, the shape is not filled; if stroke is omitted, it has no outline.

var paper = Raphael("canvas", 300, 200);
var rect = paper.rect(10, 10, 100, 50);

rect.attr({
  fill: "blue", //Solid blue fill
  stroke: "red",  //red stroke
  "stroke-width": 5 //Stroke width of 5 pixels
});

var circle = paper.circle(150, 100, 40);
circle.attr({stroke: "green"}); //Only a green stroke, no fill

Color Definitions

Colors can be specified in several ways:

Gradient Fills

Raphael.js supports linear and radial gradients for fills. These are defined using the attr() method with a specific format for the fill attribute.

Linear Gradient:

var rect = paper.rect(10, 150, 100, 50);
rect.attr({
  fill: "90-#000-#fff" // Linear gradient from black to white, angle 90 degrees
});


//More detailed linear gradient.  Note that gradient stops can be specified with an offset.
var rect2 = paper.rect(120, 150, 100, 50);
rect2.attr({fill: "l(0,0)0:#ff0000:10#00ff00:20#0000ff"}); // linear gradient with specified stops

Radial Gradient:

var circle = paper.circle(200, 100, 40);
circle.attr({
    fill: "r(0.5,0.5,0.3)#f00-#00f" // radial gradient from red to blue
});

The syntax for gradients might vary slightly depending on the Raphael.js version. Check the official documentation for your version.

Stroke Styles

Besides stroke color, you can control the stroke style with these attributes:

var path = paper.path("M10,10 L100,10 L100,100 L10,100 Z");
path.attr({
  "stroke-width": 10,
  "stroke-linecap": "round",
  "stroke-linejoin": "round",
  "stroke-dasharray": "10,5"
});

Opacity

Opacity controls the transparency of both fill and stroke. It’s set using the "opacity" attribute, with a value between 0 (fully transparent) and 1 (fully opaque).

var ellipse = paper.ellipse(150, 175, 30, 20);
ellipse.attr({
  fill: "rgba(0,0,255,0.5)", //Blue with 50% opacity
  "opacity": 0.7 //Overall opacity affecting both stroke and fill
});

Note that the opacity applied directly to the fill attribute via RGBA and the overall opacity applied via the opacity attribute will interact. The resulting opacity will be the product of the two.

Text and Typography

Text Attributes

Raphael.js provides several attributes to control the appearance of text elements. These attributes are set using the attr() method, similar to other shape attributes. Key attributes include:

var paper = Raphael("canvas", 300, 200);
var text = paper.text(100, 50, "Sample Text");
text.attr({
  "font-family": "Times New Roman",
  "font-size": 20,
  "font-weight": "bold",
  "fill": "blue",
  "text-anchor": "middle"
});

Font Families

Raphael.js uses browser-available fonts. If a specified font is not available, the browser will substitute a default font. To ensure consistent rendering across different systems, it’s a good practice to provide fallback fonts. You can list multiple font families separated by commas in the font-family attribute (e.g., "font-family": "Arial, Helvetica, sans-serif").

Font Sizes

Font size is specified in pixels using the font-size attribute. The value should be a numerical value followed by “px”. Larger values result in larger text.

Text Alignment

Text alignment is controlled using the text-anchor attribute. The three possible values are:

The anchor point (defined by x and y) is relative to the alignment. For example, with "text-anchor": "middle", the x coordinate positions the center of the text.

Text Wrapping

Raphael.js itself doesn’t directly support text wrapping. To achieve text wrapping, you will typically need to use a combination of techniques:

  1. Measure Text Width: Use text.getBBox().width to get the width of the rendered text. This requires the text element to be already rendered on the page.

  2. Split the Text: Divide the text into multiple lines using JavaScript based on your desired line width.

  3. Create Multiple Text Elements: Create multiple paper.text() elements, placing each line at the appropriate vertical position, and setting the x and y coordinates accordingly.

This approach allows you to manually break the text into lines, offering full control over the text layout, but involves more manual coding. Consider external libraries if more sophisticated text wrapping is required.

Event Handling

Attaching Event Handlers

Raphael.js allows you to attach event handlers to shapes using the standard DOM event model. The most common way is to use the on() method. This method takes two arguments: the event type (e.g., “click”, “mouseover”, “mouseout”, “mousedown”, “mouseup”, “mousemove”, “dblclick”, “touchstart”, “touchmove”, “touchend”) and a callback function.

var paper = Raphael("canvas", 300, 200);
var rect = paper.rect(50, 50, 100, 50);

rect.on("click", function() {
  console.log("Rectangle clicked!");
  this.attr({ fill: "red" }); //Change the fill on click
});

rect.on("mouseover", function() {
  this.attr({ fill: "yellow" }); //Change fill on mouseover
});

rect.on("mouseout", function(){
    this.attr({fill: "blue"}); //Change fill back to blue when mouse leaves
});

The callback function receives an event object as an argument, providing information about the event. The this keyword inside the callback function refers to the Raphael element (the shape) that triggered the event.

Event Types

Raphael.js supports a wide range of standard DOM events. Some of the most commonly used events include:

Event Propagation

Event propagation refers to the order in which events are handled when nested elements are involved. In Raphael.js, event propagation follows the standard DOM event model:

By default, Raphael events bubble up the DOM tree. You can prevent event bubbling using the event.stopPropagation() method within your event handler.

var paper = Raphael("canvas", 300, 200);
var rect1 = paper.rect(50, 50, 100, 50);
var rect2 = paper.rect(70, 70, 50, 50); //Nested rect inside rect1


rect1.on("click", function(event){
    console.log("rect1 clicked!");
});

rect2.on("click", function(event){
    console.log("rect2 clicked!");
    event.stopPropagation(); //Prevents event from bubbling to rect1
});

In this example, clicking on rect2 will only log “rect2 clicked!”, because event.stopPropagation() prevents the event from bubbling up to rect1. Clicking on the area of rect1 that is not covered by rect2 will log both “rect1 clicked!” and “rect2 clicked!”.

Advanced Techniques

Creating Custom Shapes

While Raphael.js provides basic shapes, you can create custom shapes using paths or by combining multiple shapes into more complex structures. For truly custom shapes, consider creating your own shape-drawing functions that generate path strings based on parameters you define. This allows you to reuse your custom shape creation logic throughout your application.

// Example: Function to create a rounded rectangle
function createRoundedRect(x, y, width, height, cornerRadius) {
  var pathStr = "M" + x + "," + (y + cornerRadius) + 
               " L" + (x + width - cornerRadius) + "," + y +
               " Q" + (x + width) + "," + y + " " + (x + width) + "," + (y + cornerRadius) +
               " L" + (x + width) + "," + (y + height - cornerRadius) +
               " Q" + (x + width) + "," + (y + height) + " " + (x + width - cornerRadius) + "," + (y + height) +
               " L" + (x + cornerRadius) + "," + (y + height) +
               " Q" + x + "," + (y + height) + " " + x + "," + (y + height - cornerRadius) +
               " L" + x + "," + (y + cornerRadius) + " Z";
  return paper.path(pathStr);
}

var paper = Raphael("canvas", 300, 200);
var myRoundedRect = createRoundedRect(50, 50, 100, 50, 10); //Creates a rounded rectangle with 10px corner radius
myRoundedRect.attr({fill: "lightgreen"});

Working with Groups

Raphael.js allows grouping shapes together using the paper.set() method. Grouping is useful for applying transformations or events to multiple shapes simultaneously.

var paper = Raphael("canvas", 300, 200);
var circle = paper.circle(50, 50, 20);
var rect = paper.rect(70, 70, 40, 40);

var group = paper.set(circle, rect); // Group the circle and rectangle

//Apply transformation to the entire group
group.translate(100, 0);

// Apply an event handler to the group
group.on("click", function(){
    this.attr({fill: "orange"});
});

Remember that events on a group will bubble up to the individual elements. If you need finer-grained control over event handling on the group’s elements consider using event delegation.

Using Raphael with Other Libraries

Raphael.js can be integrated with other JavaScript libraries. Common use cases involve using it alongside animation libraries (like GreenSock/GSAP) for more sophisticated animations, or with UI frameworks for creating interactive components.

Performance Optimization

For complex graphics, performance optimization is crucial. Consider these strategies:

Debugging

Debugging Raphael.js applications often involves standard JavaScript debugging techniques. Use your browser’s developer tools (console, debugger) to inspect variables, set breakpoints, and step through your code. Pay close attention to error messages in the console, as they often provide valuable clues to identify issues. Remember to check the Raphael.js documentation and community forums for troubleshooting assistance, as many common problems and their solutions are already documented.

Common Use Cases

Creating Charts

Raphael.js is well-suited for creating various types of charts, including bar charts, pie charts, line charts, and scatter plots. While Raphael.js itself doesn’t provide built-in charting functions, its ability to create and manipulate vector graphics makes it a good foundation for building custom charting components. You’ll typically need to handle data processing, scaling, and visual representation yourself.

For example, to create a bar chart, you’d:

  1. Process Data: Extract relevant data from your dataset.
  2. Calculate Dimensions: Determine the dimensions of each bar based on the data and available space on the canvas.
  3. Create Rectangles: Use paper.rect() to create rectangles representing the bars, positioning them according to the calculated dimensions.
  4. Style the Chart: Apply colors, labels, axes, and other visual elements using attr().

The complexity will increase with the type of chart you are implementing. Consider using a dedicated charting library (built on top of or alongside Raphael.js) for more advanced charting needs and features such as tooltips and legends that handle complexities such as responsive design and data interaction efficiently.

Creating Interactive Diagrams

Raphael.js enables the creation of interactive diagrams, allowing users to interact with elements. This often involves combining shape creation with event handling. For example, you could create a flowchart where clicking on a shape triggers an action or opens a detail view, or a network diagram where hovering over nodes highlights connections.

var paper = Raphael("canvas", 500, 300);
var rect = paper.rect(50, 50, 100, 50);
rect.attr({fill: "lightblue"});

rect.on("click", function() {
    //Action to be performed on click
    alert("Rectangle clicked!");
});

//Example of highlighting on mouseover
rect.on("mouseover", function() {
  this.attr({ stroke: "red", "stroke-width": 3 });
});

rect.on("mouseout", function() {
  this.attr({ stroke: "black", "stroke-width": 1 });
});

More complex interactive diagrams would involve carefully managing state and updating the visual elements based on user interactions.

Creating Animations

Raphael.js’s animate() method is powerful for creating smooth animations. You can animate various attributes, including position, size, color, opacity, and even path data. This allows you to create visually appealing effects such as transitions, transformations, and dynamic updates.

var circle = paper.circle(100, 100, 30);
circle.attr({fill: "blue"});

//Animate the circle's radius and color over 2 seconds
circle.animate({r: 50, fill: "red"}, 2000, "bounce"); // "bounce" is an easing function

//Animate the circle's position
setTimeout(function(){
    circle.animate({cx: 250, cy: 100}, 1000);
},2000);

Combining animations with event handling enables creating dynamic and responsive visuals, enhancing the user experience. Remember to consider performance when implementing many animations simultaneously. More complex animations might require a more advanced animation library in conjunction with Raphael.js.

Reference

This section provides a concise overview of the key components of the Raphael.js API. For the most complete and up-to-date information, always refer to the official Raphael.js documentation. The API may change slightly between versions.

API Reference

The core of the Raphael.js API revolves around the Raphael object, which is created when you initialize the library. This object provides methods for creating shapes, manipulating attributes, and handling events. The structure is generally as follows:

  1. Paper Object Creation: var paper = Raphael("containerID", width, height); This creates a drawing surface within the HTML element with the specified ID.

  2. Shape Creation: The paper object provides methods for creating various shapes (e.g., paper.circle(), paper.rect(), paper.path(), paper.ellipse(), paper.text(), paper.image()). These methods return a Raphael element object.

  3. Element Manipulation: Raphael elements have methods for manipulating attributes (attr()), applying transformations (translate(), scale(), rotate(), transform()), and attaching event handlers (on()).

  4. Animation: The animate() method allows for smooth changes to element attributes over time.

  5. Sets: paper.set() creates a collection of elements, enabling batch operations.

Global Functions

Raphael.js doesn’t have many globally accessible functions besides the main Raphael function itself used for initialization. Most functionality is accessed through the paper object and element methods.

Element Methods

Raphael elements (returned by shape creation methods) have a rich set of methods for manipulation:

This is not an exhaustive list. Consult the official Raphael.js documentation for a complete API reference, including details on parameters, return values, and supported attributes for each method. Remember that specific methods and attributes might have changed slightly across versions.