Monday, October 1, 2012

Raphaël: Getting/Setting SVG Element Attributes

Raphaël is a nice library for working with SVG objects.  It uses a similar syntax to jQuery for getting/setting attribute properties on an element. Unlike the normal DOM elements which use the style attribute to manage the appearance of an element, SVG uses individual attributes in the tag to define the styling options (some of these can also be placed in the style tag, but for consistency, I prefer using attributes). As a result, when working with SVG elements, you make heavy use of the attr() function instead of the css() function. Both have an identical syntax, however, the css() function only affects the style attribute of the element. Technically, you can use attr() to set the style attribute but you can't set individual styles, just the whole string. As in jQuery, Raphaël has a attr() function to get/set the individual attributes on a SVG element. There is more than one way to call the attr() function. The flexibility of the function in both jQuery and Raphaël allows you to pick the method appropriate for what you're trying to achieve.

Using jQuery, one variation allows you to set one attribute at a time by passing a string as the first argument and the value as the second:



$('#mySVG')
.attr('stroke-width', 2);



Here, we use the actual attribute name with the hyphen. Raphaël allows the same syntax. If you do not pass the second argument, both libraries will return the current value of stroke-width.

If you have several attributes to set, you can pass an object hash to attr():



$('#mySVG')
.attr({
strokeWidth: 2,
fill: 'blue'
});



Notice how you can use camel case in this situation. This is where jQuery and Raphaël differ. It turns out you can't use camel case when passing an object hash to attr(). Instead, you must quote the object keys that contain hyphens to avoid a Javascript error:



// rect is a Raphaël Element:

rect.attr({
'stroke-width': 2,
fill: 'blue'
});



Similarly, if you get the attributes on an element, they will not be camel cased. You will not be able to use dot access on the returned object. You will need to use the square bracket method:



var a = rect.attr({
'stroke-width': 2,
fill: 'blue'
});

// Will not work and will throw an error
// ReferenceError: invalid assignment left-hand side
sw = a.stroke-width;

// Use this instead
sw = a['stroke-width'];



It was not clear in the Raphaël documentation that the camel case alternative was either valid or invalid. However, after a significant amount of time rechecking my code for issues and digging through the Raphaël source, it does appear that camel case is not a valid syntax. Maybe this is a no-brainer for some who may not be using jQuery. However, its something to be aware of if you are familiar with the jQuery approach. The nice feature of the having the camel case alternative is the ability to work with objects using any of the available Javascript object access methods and not have to deal with quoting them or other errors due to the invalid hyphen character.