Search code examples
svgraphaeltransformscale

RaphaelJS applying a custom transform


I am having trouble with applying a transformation to each path in my SVG. I know the exact transform I need to add as I am using a map from wikimedia and have tested it by adding it using firebug/chromebug.

I need to add:

transform="translate(0,239) scale(0.016963,-0.016963)"

This is an example of what I have: http://jsfiddle.net/m7t4X/1/

If you inspect it, each path looks like this:

<path fill="#ff0000" stroke="#ccc6ae" d="M16760,5958C16752,5945,16745,5920,16743,5901C16740,5859,16734,5853,16710,5868C16694,5878,16690,5878,16690,5866C16690,5858,16696,5849,16703,5846C16709,5843,16705,5843,16693,5846C16670,5851,16666,5845,16669,5808C16670,5799,16666,5789,16660,5785C16655,5782,16650,5770,16650,5760C16650,5747,16645,5743,16635,5746C16626,5750,16620,5746,16620,5737C16620,5717,16549,5667,16495,5649C16473,5642,16451,5632,16446,5628C16440,5624,16426,5620,16413,5620C16395,5620,16390,5615,16390,5593C16390,5577,16381,5552,16371,5536C16351,5506,16351,5482,16371,5367C16383,5300,16383,5298,16354,5242C16338,5211,16321,5182,16317,5179C16282,5154,16269,5063,16294,5016C16302,5000,16306,4972,16303,4946C16300,4920,16302,4900,16309,4896C16315,4892,16320,4881,16320,4871C16320,4849,16350,4820,16373,4820C16382,4820,16390,4816,16390,4810C16390,4795,16442,4799,16464,4815C16475,4823,16496,4830,16511,4830C16541,4830,16580,4870,16580,4899C16580,4908,16586,4924,16594,4935C16601,4946,16613,4980,16620,5010C16628,5040,16642,5081,16651,5101C16661,5121,16675,5159,16681,5186C16688,5213,16710,5278,16731,5332C16752,5385,16772,5446,16775,5467C16787,5539,16790,5550,16803,5547C16815,5545,16816,5554,16804,5630L16797,5675L16817,5651L16837,5626L16854,5658C16866,5682,16868,5695,16860,5709C16855,5720,16850,5749,16850,5773C16850,5797,16845,5832,16839,5851C16825,5895,16786,5979,16780,5980C16777,5980,16768,5970,16760,5958Z" stroke-opacity="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); stroke-opacity: 1;"></path>

If I add it manually via firebug etc to change the start to look like this:

<path  transform="translate(0,239) scale(0.016963,-0.016963)" fill="#ff0000" stroke="#ccc6ae" d="

then it works perfectly. I just cannot replicate this.

I have tried various ways of adding the transform, but none have worked fully. From what I gather, RaphaelJS is backwards compatible so all of the solutions I have found (which haven't fully worked anyway) wouldn't have worked in any older IEs for instance.

The first thing I tried was to change:

paper.setViewBox(0, 0, w, h, true);

to:

paper.setViewBox(true);

However this did not work with the shapes I am using (http://upload.wikimedia.org/wikipedia/commons/9/95/Continents.svg)

This is where I got the transform amounts from (can be seen if you view source).

Please advise on where I'm going wrong, and how I could go about adding this.

Many thanks!

---------------------------------EDIT -------------------------------------

After applying the fix below, I have found it appears to be displaying the SVG rotated 180degrees and flipped horizontally. I don't quite understand why either.

This is how it is meant to look: enter image description here

And this is how it comes out: enter image description here

(also noticed I'm missing south america despite it being referenced)

This is a new fiddle of how it currently looks:

http://jsfiddle.net/wrayvon/m7t4X/3/

Thanks again


Solution

  • The transform should work, but I think you just need to set a bigger width/height for the viewBox. These should be for the co-ordinate space, not for pixels on screen.

    var w = 15000;
    var h = 25000;
    
    paper.setViewBox(10000, 0, w, h, true);
    

    Should do it. You can also transform it if you want, by adding something like the following to the element when created.

    .transform('t2000,1000') 
    

    edit: As you have changed the SVG... If there are transforms in the original, you will probably need to apply the same transforms to the elements...so a line like this...

    var c = paper.path(worldmap.shapes[country]).attr({ stroke: "#ccc6ae", fill: "#ff0000", "stroke-opacity": 1 }).transform('s1,-1,13000,10000');
    

    I'm just guessing the centre point to scale from there (13,000,10,000 its probably a bit more), you will need to figure that separately.

    Or you could match the scale as per the original SVG, and then you probably won't need to change the viewBox (apart from matching the original).

    Original jsfiddle

    Updated jsfiddle