Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotate a scalable and translated SVG element around its center

Tags:

svg

I'm trying to rotate paths inside an SVG.

Because rotating in an SVG works different than it does with other html elements via CSS (ie. the default axis in SVG is the element's top left corner instead of its center), I've run into lots of problems.

I need to rotate the paths using their center points as the axis. I can do it by setting transform-origin to 50% 50%, however I also need to translate & scale the paths, and changing the transform-origin fudges the translations.

Pretending the path is a static size, I can do it by including the x/y as half the path's width/height in "rotate(90, x, y)". However, the SVG responsively scales to fit the window size, so the path's width/height is dynamic. (ie. if I set the location for the axis of rotation correctly at a given size, it warps more and more incorrectly as the window changes size. I didn't find a way to do this using percentages-- please tell me if you're aware of a way!)

I think I'm probably missing something incredibly simple but I've floundered on figuring it out myself. How do I rotate these paths-- dynamically sized paths with translations-- using their center as the axis?

(I also experimented applying some of the transforms to a parent element, but this only resulted in the path clipping)

The basic problem:

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000">
        <g>
        <path class="A" transform="translate(1000 1000) rotate(0) scale(20)" d="m23.5,2 16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z" d="m23.5,2 16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z"/>
        <path class="B" transform="translate(1000 1000) rotate(45) scale(20)" d="m23.5,2 16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z" d="m23.5,2 16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z"/>
        <path class="C" transform="translate(1000 1000) rotate(90) scale(20)" d="m23.5,2 16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z" d="m23.5,2 16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z"/>
        </g>
    </svg>

I can't get the centers of A, B, and C to share one x/y coordinate while maintaining their translations & responsiveness.

Thanks

like image 234
JMcFar Avatar asked Nov 22 '25 12:11

JMcFar


1 Answers

Well the easiest way to do this is to draw the original shapes at the origin, then rotate them, then scale them, then move them into the final position that you want. So change that initial relative m to an absolute M and move the initial drawing point so that the center of the arrow will coincide with the origin. (You need to add the "l" to toggle the rest of the path back to relative draw.)

Transforms are applied in reverse order, so you want your rotate last (applied first) and your translate first (applied last).

(I've added fill-opacity so you can see what's happening a bit better)

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 2000 2000">
        <g>
        <path class="A" transform="translate(1000 1000) scale(20) rotate(0)"  d="M 0.75,-14.3 l16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z" fill-opacity="0.5"/>
        <path class="B" transform="translate(1000 1000) scale(20) rotate(45)" d="M 0.75,-14.3 l16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z" fill-opacity="0.5"/>
        <path class="C" transform="translate(1000 1000) scale(20) rotate(90)" d="M 0.75,-14.3 l16.5,14.3-16.5,14.3v-6.8h-15v-15h15v-6.8z" fill-opacity="0.5"/>
        </g>
    </svg>
like image 91
Michael Mullany Avatar answered Nov 25 '25 03:11

Michael Mullany



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!