Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating Nested SVG

I am using SVG.js and trying to make some manipulations with SVG. I was previously working with canvas but I was very disappointed with the quality of the images it was generating so I've decided to use pure SVG.

I managed to change everything into a pure SVG approach, everything except one thing: rotation.

I cannot make it work. I would love to use what the SVG.js library offers, but that didn't work. I also have tried fiddling with the elements inside but also without success. The best link I found up to this point was this one but although he manages to rotate the images separately, it does not show how to rotate everything together (which is my case)

What I want

I want to be able to rotate an SVG image which I've created in Inkscape (fairly simple)

Problem

No rotation at all, through several methods and opinions on the internet.

What I've tried

  • using the transform attribute with rotate(45)
  • using the SVG.js built in method
  • reading about how rotation cannot be applied to <g> tag
  • reading about how the SVG rotation is different from the CSS in respect to its coordinate system (e.g. this link from css-tricks)

Example of problem

Here I have a simple SVG of a player which I put as a JS variable. The image is created and moved to the coordinates = (50, 50). Finally I try to rotate it 45 degrees. (Which does not help)

const player = '<svg width="11.214mm" height="6.3195mm" version="1.1" viewBox="0 0 11.214 6.3195" xmlns="http://www.w3.org/2000/svg">&gt;\n' +
    ' <g transform="translate(-172.04 62.213)">\n' +
    '  <g transform="matrix(.429 0 0 .429 160.68 -80.101)">\n' +
    '   <g stroke="#000">\n' +
    '    <path d="m39.592 42.246c-4.5716 0.02368-12.788-1.0453-12.77 6.7945 0.01784 7.8398 12.788 6.8319 12.788 6.8319s12.667 1.041 12.681-6.9252-8.1273-6.7249-12.699-6.7012z" fill="#ff2a2a" stroke-width=".20436px"/>\n' +
    '    <circle cx="39.556" cy="49.061" r="7" fill="#ffb380" stroke-width=".26458"/>\n' +
    '   </g>\n' +
    '  </g>\n' +
    ' </g>\n' +
    '</svg>';

    if (SVG.supported) {
    	const drawArea = SVG('svgDrawArea').size(300, 300);
      
      const group = drawArea.nested();
      group.svg(player);
      group.move(50, 50);
      
      group.transform({ rotation: 45 });
    } else {
        alert('SVG not supported')
    }
    
#svgDrawArea{
  /* background-color: red; */
  height: 300px;
  width:300px;
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.4/svg.min.js"></script>
<div id="svgDrawArea"></div>

I would be happy if someone can explain why the rotation does not work or to point me to somewhere where I can clarify myself on the why!

like image 739
fditz Avatar asked Oct 27 '25 09:10

fditz


2 Answers

Your problem is due to the fact that, in SVG 1.1, the <svg> element did not allow the transform attribute. It is now allowed in SVG 2, but only Firefox has implemented that so far. Chrome has not yet.

The solution is to append a group first, then put the SVG in that group. You can then transform that group instead, and it will work in both browsers.

Just as @noob has suggested in their answer. Feel free to accept their answer if you like.

like image 162
Paul LeBeau Avatar answered Oct 28 '25 21:10

Paul LeBeau


sorry, only a solution, but no explanation (having my own problems with rotating svg paths, I know your pain)

I used

group.transform({ x: 50, y:50});
group.transform({ rotation: 45 });

const player = '<svg width="11.214mm" height="6.3195mm" version="1.1" viewBox="0 0 11.214 6.3195" xmlns="http://www.w3.org/2000/svg">&gt;\n' +
    ' <g transform="translate(-172.04 62.213)">\n' +
    '  <g transform="matrix(.429 0 0 .429 160.68 -80.101)">\n' +
    '   <g stroke="#000">\n' +
    '    <path d="m39.592 42.246c-4.5716 0.02368-12.788-1.0453-12.77 6.7945 0.01784 7.8398 12.788 6.8319 12.788 6.8319s12.667 1.041 12.681-6.9252-8.1273-6.7249-12.699-6.7012z" fill="#ff2a2a" stroke-width=".20436px"/>\n' +
    '    <circle cx="39.556" cy="49.061" r="7" fill="#ffb380" stroke-width=".26458"/>\n' +
    '   </g>\n' +
    '  </g>\n' +
    ' </g>\n' +
    '</svg>';

    if (SVG.supported) {
    	const drawArea = SVG('svgDrawArea').size(300, 300);
      
      const group = drawArea.nested();
      group.svg(player);
      
     // group.rotate(45);
      //group.move(50, 50);
      group.transform({ x: 50, y:50});
      group.transform({ rotation: 45 });
    } else {
        alert('SVG not supported')
    }
    
#svgDrawArea{
  /* background-color: red; */
  height: 300px;
  width:300px;
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.4/svg.min.js"></script>
<div id="svgDrawArea"></div>
like image 24
noob Avatar answered Oct 28 '25 22:10

noob



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!