views:

179

answers:

1

I really like the Raphael Javascript library which is very useful for handling SVG with javascript.

However there is an offset value which is added to the generated svg code that I don't understand. Does anybody know where does it come from and how to avoid it?

Here is my JS code:

var paper = Raphael("canvas", 510, 510);
paper.clear();
paper.rect(0, 0, 500, 500, 10).attr({fill: "#fff", stroke: "black"});

The generated SVG code is

<div id="canvas">
    <svg width="510" height="510">
        <desc>Created with Raphaël</desc>
        <defs/>
        <rect x="0.5" y="0.5" width="500" height="500" r="10" rx="10" ry="10" fill="#ffffff" stroke="#000000"/>
    </svg>
</div>

Why does the x and y attributes of the rect are 0.5 and not 0?

Update: It seems that the values are rounded with the code below:

var round = function (num) {
    return +num + (~~num === num) * .5;
};

Does anybody know the reason?

+5  A: 

The expression +num + (~~num === num) * .5 is saying:

  1. +num: get the value of the variable num as a number;
  2. (~~num === num): return true if the bitwise-NOT of the bitwise_NOT of the value of the variable num (which is num with any fractional component removed, equivalent to Math.floor(num)) is exactly equal to the value of the variable num: that is, return true if num is an integer, false otherwise;
  3. add the result of step 1 to the result of step 2, thereby coercing the Boolean value returned by step 2 into a numeric value: for the case when the variable num has the numeric value 0, this will result in 1;
  4. multiply the result of step 3 by 0.5.

So we get the result (0 + 1) * 0.5, which is 0.5.

In other words, the code is saying "For all integers, add 0.5; for all non-integers, add nothing."

This has some interesting results whose purpose is obscure to say the least; consider its application to the following values:

  1. 0 -> 0.5;
  2. 0.1 -> 0.1;
  3. 0.4 -> 0.4;
  4. 0.5 -> 0.5;
  5. 0.9 -> 0.9;
  6. 1.0 -> 1.5;
  7. 1.1 -> 1.1;

...and so on.

As to why they do this: I really haven't got the faintest idea. FWIW I've got large amounts of SVG, both static and dynamically created, working happily on Firefox, Safari and Opera, and none of it has ever needed this kind of silliness.

If anybody ever finds out the reason for this, I'd love to know it :-)

NickFitz
Thanks, great explanation. Raphael is also supporting IE thanks to VML. Might be related?
luc
Apparently not: the function in question is defined under a comment saying "SVG", and inside an if clause: *if (R.svg) {* so I think it's definitely on the SVG branch ;-)
NickFitz
I forgot to accept your answer. Sorry.
luc
@luc - No problem. Thanks for remembering after all this time :-)
NickFitz