RaphaelJS not only creates elements, but it also allows the manipulating or transforming of any element and its properties dynamically.
By the end of this section, you would know how to transform a shape.
There might be many scenarios wherein you might need to modify a shape dynamically. For example, when the user mouse-overs a circle, you might want to scale up that circle just to give a visual feedback to the user. Shapes can be manipulated in RaphaelJS using the transform()
method.
Transformation is done through the transform()
method, and it is similar to the path()
method where we add the path string to the method. transform()
works in the same way, but instead of the path string, it's the transformation string. There is only a moderate difference between a transformation string and a path string.
There are four commands in the transformation string:
The fourth command, M
, is of little importance and let's keep it out of the way, to avoid confusion.
Note
The transformation string might look similar to a path string. In reality, they are different, not entirely but significantly, sharing little in common. The M
in a path string means move to, whereas the same in a transformation string means Matrix. The path string is not to be confused with a transformation string.
As with the path string, the uppercase letters are for absolute transformations and the lowercase for relative transformation. If the transformation string reads r90T100,0
, then the element will rotate 90 degrees and move 100 px in the x axis (left). If the same reads r90t100,0
, then the element will rotate 90 degrees and since the translation is relative, it will actually move vertically down 100px, as the rotation has tilted its axis.
I am sure the previous point will confuse most, so let me break it up.
Imagine a rectangle with a head and now this head is at the right side of the rectangle. For the time being, let's forget about absolute and relative transformation; our objective is to:
Rotate the rectangle by 90 degrees.
Move the rectangle 100px on the x axis (that is, 100px to the right).
It's critical to understand that the elements' original values don't change when we translate it, meaning its x and y values will remain the same, no matter how we rotate or move the element.
Now our first requirement is to rotate the rectangle by 90 degrees. The code for that would be rect.transform("r90")
where r
stands for rotation—fantastic, the rectangle is rotated by 90 degrees. Now pay attention to the next important step. We also need the rectangle to move 100px in the x axis and so we update our previous code to rect.transform("r90t100,0")
, where t
stands for translation. What happens next is interesting—the translation is done through a lowercase t
, which means it's relative. One thing about relative translations is that they take into account any previous transformation applied to the element, whereas absolute translations simply reset any previous transformations before applying their own.
Remember the head of the rectangle on the right side? Well, the rectangle's x axis falls on the right side. So when we say, move 100px on the x axis, it is supposed to move 100px towards its right side, that is, in the direction where its head is pointing. Since we have rotated the rectangle by 90 degrees, its head is no longer on the right side but is facing the bottom.
So when we apply the relative translation, the rectangle will still move 100px to its x axis, but the x axis is now pointing down because of the rotation. That's why the rectangle will move 100px down when you expect it to move to the right.
What happens when we apply absolute translation is something that is entirely different from the previous one. When we again update our code for absolute translation to rect.transform("r90T100,0")
, the axis of the rectangle is not taken into consideration. However, the axis of the paper is used, as absolute transformations don't take previous transformations into account, and they simply reset them before applying their own. Therefore, the rectangle will move 100px to the right after rotating 90 degrees, as intended.
Note
Absolute transformations will ignore all the previous transformations on that element, but relative transformations won't.
Getting a grip on this simple logic will save you a lot of frustration in the future while developing as well as while debugging.
The following is a screenshot depicting relative translation:
The following is a screenshot depicting absolute translation:
Notice the gap on top of the rotated rectangle; it's moved 100px on the one with relative translation and there is no such gap on top of the rectangle with absolute translation.
By default, the transform method will append to any transformation already applied to the element. To reset all transformations, use element.transform("")
. Adding an empty string to the transform method will reset all the previous transformations on that element.
It's also important to note that the element's original x,y position will not change when translated. The element will merely assume a temporary position but its original position will remain unchanged. Therefore after translation, if we call for the element's position programmatically, we will get the original x,y, not the translated one, just so we don't jump from our seats and call RaphaelJS dull!
The following is an example of scaling and rotating a triangle:
The following screenshot depicts the output of the preceding code:
The triangle is transformed using relative translation (t). Now you know the reason why the triangle has moved down rather than moving to its right.