简体   繁体   中英

CSS rotate SVG repeated <use> element around object center

I'm trying to rotate an single object which contains SVG through CSS. I'm having trouble to get the rotation around the center of the element, though 'tranform-origin' is set.

HTML:

<svg xmlns="http://www.w3.org/2000/svg" width="8.94" height="31.23" viewBox="0 0 8.94 31.23">
  <defs>
    <g id="el">
      <rect x="1.86" y="0.2" width="5.22" height="30.82" transform="translate(-1.87 0.66) rotate(-7)"></rect>
    </g>
  </defs>
</svg>

<svg class="canvas">
  <use x="49%" y="76%" href="#el"></use>
  <use x="80%" y="63%" href="#el"></use>
  <use x="5%" y="32%" href="#el"></use>
  <use x="80%" y="12%" href="#el"></use>
</svg>

CSS:

  .canvas {
  position: absolute;
  height: 100%;
  width: 100%;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

.canvas use:nth-child(4){
  fill: red;
  transform-origin: 50% 50%;
  transform: rotate(20deg);
}

I made a JSfiddle to make things clear. What I'm trying to do is rotating the red element 20deg around it's own center. But it keeps rotating around the top left corner.

For SVG elements, unlike HTML, the coordinate system is not defined by its local bounding box:

For SVG elements without an associated CSS layout box the horizontal and vertical offset represent an offset from the point of origin of the element's local coordinate space.

In your case, the coordinate system is that of the .canvas , and the <use> element rotates around its center.

You have to calculate the center of your element as "position + center of the bounding box", so for your element at x=80%, y=12% and a bounding box of 8.95px×31.25px:

.canvas use:nth-child(4){
    transform-origin: calc(80% + 4.475px) calc(12% + 15.625px);
    transform: rotate(20deg);
} 

I did want to post this as a comment because I feel like it's not fully solved, but it's too long to fit in a comment so here it is as an answer:

When you use the <use> tag, the transform seems to be based on if the path was in the top left. Therefore what you can do is instead of using % widths for the transform-origin use vh and vw (which only works because you have set the .canvas to be the size of the display) and set it equal to the offset of the path. This brings the center of rotation to where the path is.

So in your case, this would be:

.canvas use:nth-child(4){
  fill: red;
  transform-origin: 80vw 12vh;
  transform: rotate(20deg);
}

This works but it doesn't really solve the root problem.

 .canvas { position: absolute; height: 100%; width: 100%; top: 0; left: 0; bottom: 0; right: 0; } .canvas use:nth-child(4){ fill: red; transform-origin: 80vw 12vh; transform: rotate(20deg); } 
 <svg xmlns="http://www.w3.org/2000/svg" width="8.94" height="31.23" viewBox="0 0 8.94 31.23"> <defs> <g id="el"> <rect x="1.86" y="0.2" width="5.22" height="30.82" transform="translate(-1.87 0.66) rotate(-7)"></rect> </g> </defs> </svg> <svg class="canvas"> <use x="49%" y="76%" href="#el"></use> <use x="80%" y="63%" href="#el"></use> <use x="5%" y="32%" href="#el"></use> <use x="80%" y="12%" href="#el"></use> </svg> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM