I am using RaphaelJS for a project that requires vector drawing for visualization of some data.
I am not able to figure out how to push and pop transformation states.
(equivalent of context.save() and context.restore() in html5 canvas)
Can someone point me in the right direction?
thanks.
Could you explain why you need to push and pop transformation state?
In svg you don't really need to do that, the browsers do it for you. If you want a particular transform to apply to an element then just add a transform attribute to it. You can make a transform apply to many elements by using <g> elements (in Raphaël there's Paper.set, which can be used like a <g> element, and you have the Element.transform method to set the transforms).
Update:
context.save() - in svg terms this would be to take the current transformation matrix (CTM) of the element at a given time and storing it somewhere, in Raphaël I guess this might be Element.transform() (I'm not 100% sure if it includes whole stack of transformations or not, anyway, in pure svg the CTM can be fetched via the getCTM() method which is available on all elements). One way of doing this would be to insert a <g> element with the transformation you want.
context.restore() - in svg this would be equivalent to removing a transformation from the list of transforms, but note that in svg siblings don't "inherit" the transformation (this is unlike html5 canvas or OpenGL where the currently set matrix is just applied to anything you draw after setting the transform). If you want a transform to apply to many elements then you create a <g> which has the transformation that should apply to all the children of that element, and to restore you just insert elements to the parent of the <g> instead. Raphaël doesn't have any built-in support for the <g> element (unless you count Element.set, which is a similar concept), a guess for why Raphaël does this is that it's to prevent people from trying to do things like this since it becomes very easy to bloat the DOM without realizing it (remember, SVG is a retained mode graphics format, unlike canvas and OpenGL).
Related
I am using Inkscape to make SVG image and a little confused about the "transform-center-x" attribute like below:
<circle
style="display:inline;fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.13386"
id="beacon-21737"
cx="-121.04593"
cy="42.20393"
r="1.9999999"
inkscape:transform-center-x="-0.6614634"
inkscape:transform-center-y="-10.318751"
inkscape:label="beacon"
transform="rotate(-90)">
</circle>
It seems not equal to rotate(angle, x, y). Please help me understand the meaning of the "transform-center-x/y".
This is a property of the grafical interface. If you click twice on a grafical object, you can rotate or skew it around a center indicated by a cross:
The cross can be moved by dragging it. Its position is stored in the inkscape:transform-center attribute. The value is in coordinates relative to the center of the bounding box of the grafical object. This position will also be used for other transforms, for example when you use the Object -> Transformation... dialog.
The SVG namespace transform will not reflect that center. Inkscape has an internal optimization algorithm to express rotations and other transforms, so the grafical and the standardized center might not coincide.
As always, other renderers will simply ignore tags and attributes in the inkscape namespace.
My objective here is to allow users to specify territories or regions given a background world-map overlay, which is an SVG generated from GeoJSON data using D3. I have done the part where the territories' points are pinpointed by the user, and an SVG is generated. This works well.
Now I would like to save the territory's coordinates, using the background map's projection, scale and translation. I saw a lot of documentation about translating GeoJSON data to SVG s, but nothing about the other way. Is it even possible ?
Thanks Ben Lyall, eventually I used the native SVG functions getTotalLength() and getPointAtLength() to convert my path to an array of top/left positions (in pixels), then d3's projection.invert() to translate them into coordinates.
I am new to svg, as far as I saw everywhere they using svg elements within g tag, is there any particular reason for using svg elements within g tag other than applying transformation for whole set of elements?
That's a pretty important and useful reason. But other reasons you might do it are so you can:
apply the same styling (eg. fill="blue") to a set of elements,
reference to the group of objects from a use.
Not to mention the simple organisational reasons.
http://tutorials.jenkov.com/svg/g-element.html says:
The <g> element is used to group SVG shapes together. Once grouped you can transform the whole group of shapes as if it was a single shape. This is an advantage compared to a nested <svg> element which cannot be the target of transformation by itself.
Is there any way to create an SVG transform that would transform a square into an isosceles trapezoid to give the illusion of perspective?
I have a project (visible here) where I have one element group in the svg (the breadboard) that I would like to skew so that the bottom looks like it's a closer to the user.
I can transform the top-level SVG DOM element with a CSS transform (in supporting browsers) using something like "-webkit-transform: perspective(1000px) rotateX(40deg);", but this doesn't work in the nested group element.
Any suggestions appreciated, thanks!
Is there a way to attach metadata directly to a grouping element () in an svg file? I couldn't find anything about that in the specification or elsewhere on the web, so I assume it's not possible. Perhaps there are other ways to attach element specific metadata within the svg file...
What I try to do is to create a map and attach information about adjacent countries.
Cheers.
As XML is extensible you can add attributes and element children as you wish. Here's a possible example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:sol="http://www.sol.org">
<circle cx="10" cy="20" sol:country="ruritania" r="5"/>
</svg>
Here the svg and circle elements are in SVG namespace and sol:country is in your namespace. I believe that SVG user agents will ignore foreign namespaces. You could also use a metadata schem such as Dublin Core.
Alternatively you could use a desc element (http://www.w3.org/TR/SVG/struct.html#DescElement)
5.4 The 'desc' and 'title' elements
Each container element or graphics element in an SVG drawing can supply a 'desc' and/or a 'title' description string where the description is text-only. When the current SVG document fragment is rendered as SVG on visual media, 'desc' and 'title' elements are not rendered as part of the graphics. User agents may, however, for example, display the 'title' element as a tooltip, as the pointing device moves over particular elements. Alternate presentations are possible, both visual and aural, which display the 'desc' and 'title' elements but do not display 'path' elements or other graphics elements. This is readily achieved by using a different (perhaps user) style sheet. For deep hierarchies, and for following 'use' element references, it is sometimes desirable to allow the user to control how deep they drill down into descriptive text.