3

In Raphael, if you apply .toFront() or .toBack() to a set, it does two things:

  • The expected behaviour: All elements in that set go to the front or the back of the stacking order.
  • An unexpected behaviour: The order of the elements within the set changes

JSBin demo

Click the text buttons in the demo and notice how the order among the circles reverses, as well as the set of circles moving behind and in front of the translucent rectangle.

The same thing happens (very slightly differently) if .insertBefore() or .insertAfter() are used to move objects to the front and to the back.

My question is: how to send multiple Raphael elements .toFront() or .toBack() together, maintaining the stacking order between these elements?


I understand why this is happening: Raphael sets are basically just modified arrays, and Raphael is just haphazardly applying .toFront() or .toBack() to each element in the set in turn, so the resulting order within elements in the set depends on whatever order Raphael happens to choose for looping through the array of elements. This order appears to be the order in which the elements were pushed to the array - not the stacking order of the elements.

I'm not sure what to do about it. How can I push a selection of Raphael objects .toFront() or .toBack() while maintaining the order between the elements?

IE8 support is non-negotiable unfortunately so ideally answers should work in Raphael's VML mode as well as SVG mode. Remember that Raphael doesn't use SVG <g> groups (I believe this is because there isn't a clean VML equivalent), so the suggestion here won't work.


One idea that should work but which I can't find a clean way to implement: maybe we could sort the Raphael set array by the elements' stacking order, before applying the .toFront() or .toBack()? Then modified .setToFront() and .setToBack() functions can be defined which, maybe, clone the set array, sort the clone by stack order ascending or descending depending on whether it is to front or to back, then apply .toFront() or .toBack() to each element? I can't find any clean way of getting the object's position in the stacking order, however.

Community
  • 1
  • 1
user56reinstatemonica8
  • 32,576
  • 21
  • 101
  • 125

1 Answers1

0

Since you know that Raphael is treating the set like an array, you have realized that some workaround had to be done.

So I added a little function in you code and you can call it instead of toFront().
THIS seams to do what you were asking to and it is very nice and simple:

function correctOrder()
{
   for ( var i = 0; i < set1.length; i++)
   {
      var temp_circ = set1.pop();
      temp_circ.toFront();
      set1.splice(0, 0, temp_circ);
   }
}
Brian
  • 4,958
  • 8
  • 40
  • 56