What does inkscape:transform-center-x/y means? - svg

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.

Related

React-leaflet Circle component do not set radius

I use this component like it should be used
<Circle center={[30, 70]} fillColor={"blue"} radius={70} />
Problem is that circle look like dot no matter what is zoom level.
I must say that other components like Polygon render just normal as it should be.
Do you know what could be a problem?
The problem was in map CRS attribute.
So Circle and other components were not rendered properly.
You can see how to solve CRS attribute on this link
Set react-leaflet map CRS atribute

Is it possible to translate an SVG path to GeoJSON?

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.

How do I rotate or scale (transform) an SVG path relative to its center point?

I'm trying to rotate and scale shapes within an SVG around their center point. I've looked into several libraries, including Jquery, Greensock, D3, RaphaelJS, but I haven't been able to find any that provide a straightforward way to accomplish this. Each animates the shape from the origin point (which I understand is the default). I want to be able to spin a shape around its center point or scale it up or down from the center point.
Here are a couple examples using Greensock and D3 that illustrate the default behavior: http://jsbin.com/AHEXiPa/1/edit?html,js,output
Each of these examples bounce in and out from the top left as opposed to remaining stationary and expanding from the center of the triangle out in all directions.
Can one of the libraries I mentioned accomplish this, or is there another library or method I should consider?
Ideally, I need to be able to apply the animation/transform to an existing object in the DOM. D3 is good at this for instance, but Raphael seems to require converting an SVG to Raphael first prior to injecting it into the DOM.
Really its a case of pick the library that suits your needs, and then you will figure a way. As BigBadaboom says, if you do a search, there are lots of solutions.
To try and combine your questions, as sometimes the tricky bit is using an existing DOM object, I've included an example in Snap.svg. You can often do something similar in most libraries.
jsfiddle here Fiddle using your existing html.
s = Snap("#mySVGContainer1"); // create a canvas from existing svg
var triangle1 = s.select("#myShape1").transform("r90"); //select&transform existing object
p = Snap("#mySVGContainer2");
var triangle2 = p.select("#myShape2");
var bbox = triangle2.getBBox(); //bounding box, centre cx/cy
//rotate and scale with transform string (raphael/snap format)
triangle2.animate({ transform: "r180," + bbox.cx + ',' + bbox.cy + "s3,3," + bbox.cx + "," + bbox.cy }, 2000);
For rotations, as #Ian points out, you can specify the center of rotation. For other transformations, changes are defined relative to the path's (0,0) point.
The easiest way to get transformations to work relative to the path's center is to either:
Define the path so that it is centered around the (0,0) point; or
Wrap the path in a <g> element, and then translate it so it is centered on the (0,0) point of the <g> element's coordinate system.
Then, you can apply rotations, scales and transforms (on the <g> element, if using) and they will all be nicely centred.
The trickiest part is figuring out the "center" of an arbitrary shape. #Ian's approach of using the center of the bounding box will usually give decent results. If your shape is a polygon there are d3 functions you could use.
Example showing a shape moving with the mouse, rotating and changing scale, all centered around the center of the bounding box:
http://fiddle.jshell.net/LgfE3/
Edit: simplier jsfiddle
I've been looking for a long time, and will settle for the following.
1. Design your svg shape at coordinate x:0,y:0.
2. Identify by hand the center of rotation, by example, center = [ x:50,y:100].
3. Build a spinIt() function such :
function spinIt() {
needle.transition()
.duration(2000)
.attrTween("transform", tween);
function tween() {
return d3.interpolateString("rotate(-180, 50, 100)", "rotate(90, 50, 100)");
}
}
4. Use it on a triger:
svg.on("click", spinIt);
http://jsfiddle.net/SHF2M/79/

setting viewbox coordinates to extents of svg drawing

I have a set of dynamically created svg objects. Some of them have rather complicated transformations applied to. I mean this is meaningless that I want to calculate maximum and minimums of X & Y of these objects. I want viewbox (or any similar tag that may be useful) to show all these objects without engaging me in calculating extents of drawing objects.
Could you please help?
Thanks
You can use getBBox() on the path element to get the extents of your drawing.
var clientrect = path.getBBox();
var viewBox = clientrect.x+' '+clientrect.y+' '+clientrect.width+' '+clientrect.height;
You can then set the viewbox to these co-ordinates.
n.b. i think you can change the viewbox of an svg after it's rendered so you may have to re-render the svg.

How can we Save and Restore transformation states in RaphaelJS

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).

Resources