How to rotate SVG path without clipping and without increasing container <svg> height/width?

Viewed 55

Is it possible to rotate an svg path without clipping it? I'm aware that I can increase the size of the container, but I don't want to do this. I tried to rotate the svg container at the same angle as the path, but it doesn't work.

This is my basic svg setup:

<svg width = {600} height = {600} viewBox = "0 0 600 600">
<svg x = {10} y = {10} height = {40} width = {100} viewBox = "0 0 100 40">
<path d= {"M0 0 L100 40 M0 40 L100 0"} />
</svg>
<svg>

If I add transform={rotate(90)} transform-origin="50% 50%" to the path element, then the element rotates, but gets cutoff by the svg.

If I instead add that same code to the parent svg (the 100 width one), then absolutely nothing happens.

3 Answers

You need to reserve enough space for your path to rotate in. Without changing the container size, you can define the viewBox to include all the coordinates where the rotated path could end at. That rectangle will then be fitted into your container.

If you rotate the path around its center at (50, 20), its upper limit with a rotation of 90deg will end at y=-30. The viewBox needs to include that value.

Your code also indicates you want to move the path +10, +10 away from the upper left corner. To achieve that and leave it at its original size, set viewBox="-10 -40 600 600". That rectangle will be fit into your outer <svg>, without the need to define an inner one.

<svg width="600" height="600" viewBox="-10 -40 600 600">
  <path d="M0 0 L100 40 M0 40 L100 0" stroke="red" />
  <path transform="rotate(90, 50, 20)" d="M0 0 L100 40 M0 40 L100 0" stroke="blue" />
</svg>

In general it depends on the use case. Here are two examples that might help where I place the cross using the transform attribute. The red cross is your original path where 0,0 is in the upper left corner. Here I translate the first and then rotate. The same happens with the blue cross, but here I have moved 0,0 to the middle of the cross. This can help in cases where the element needs to rotate a lot or copied around.

svg {
  border: solid thin black;
  display: block;
}
<svg width="200" height="200" viewBox="0 0 100 100">
  <path d="M0 0 L100 40 M0 40 L100 0"
  transform="translate(70 0) rotate(90)"
  stroke="blue" />
</svg>

<svg width="200" height="200" viewBox="0 0 100 100">
  <path d="M -50 -20 L 50 20 M -50 20 L 50 -20"
  transform="translate(50 50) rotate(90)"
  stroke="red" />
</svg>

Thank you everyone for the great answers. I haven't tested all the solutions yet, but I bet that each answer works best for different situations. However, I figured out a way that worked best for me. As shown in my question, I do have a "parent" svg that is quite large, but I needed help rotating the smaller svg properly while making sure paths/polygons inisde the smaller svg don't clip. I ended up surrounding the "small" svg tag with a g tag, and then applied the rotation transform to the g tag. This made the svg as a whole rotate, and rotated the inner contents of the svg as well. The end result looked something like this:

<svg width = {600} height = {600} viewBox = "0 0 600 600">
<g transform = "rotate(90)">
<svg x = {10} y = {10} height = {40} width = {100} viewBox = "0 0 100 40">
<path d= {"M0 0 L100 40 M0 40 L100 0"} />
</svg>
</g>
<svg>

It did look a little bit different since I was using React.js, but that was the gist of it.

Related