Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 751
Matt Avatar asked Jan 28 '14 17:01

Matt


People also ask

How do I rotate a path in SVG?

Just use the element type selector and add the transform: rotate(180deg) property to it like in the below snippet. Show activity on this post. Inline you would do it like this: x-axis flip : transform="scale(-1 1)"

How do you rotate a shape in SVG?

The rotate(<a> [<x> <y>]) transform function specifies a rotation by a degrees about a given point. If optional parameters x and y are not supplied, the rotation is about the origin of the current user coordinate system. If optional parameters x and y are supplied, the rotation is about the point (x, y) .

How do you flip an SVG upside down?

The simplest would possibly be to use a CSS transform to rotate by 180 degrees. Since the initial value for transform-origin is 50% 50% 0 the rotation happens around the center. This avoids the need to actually modify the SVG. Note that this doesn't actually "flip", but rotate.


3 Answers

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);  
like image 140
Ian Avatar answered Oct 07 '22 00:10

Ian


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:

  1. Define the path so that it is centered around the (0,0) point; or
  2. 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

like image 35
AmeliaBR Avatar answered Oct 07 '22 01:10

AmeliaBR


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/

like image 1
Hugolpz Avatar answered Oct 07 '22 01:10

Hugolpz