SVG Won't Rotate Correctly

Viewed 556

My SVG is rotating from a point on the right of the actual SVG I would like it to rotate from the center of the SVG. I have tried transform-origin: 50% 50%; and that did not work. I have also messed with all of the other settings to no prevail.

Here is my current code:

body {
  background-color: black;
}

.rotate {
  animation: rotation 8s infinite linear;
  opacity: 1;
  width: 1400px;
  position: absolute;
  top: -70px;
  right: -195px;
}

.rotate:hover {
  opacity: 1;
  transition: 0.4s
}

.rotate svg {
  transform-origin: center;
}

@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
<div class="rotate">
  <?xml version="1.0" encoding="utf-8"?>
  <!-- Generator: Adobe Illustrator 24.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 500" style="enable-background:new 0 0 1200 500;">
                    <style type="text/css">
                        .st0{fill:none;}
                    </style>
                    <path id="SVGID_x5F_1_x5F_" class="st0" d="M638,358.5c0,40.59-32.91,73.5-73.5,73.5S491,399.09,491,358.5s32.91-73.5,73.5-73.5
                        S638,317.91,638,358.5z"/>
                    <text><textPath  xlink:href="#SVGID_x5F_1_x5F_" startOffset="0%">
                    <tspan  style="fill:#FFFFFF; font-family:'fatboy-slim'; font-size:40px; letter-spacing: 0px;">Visit Me Visit Me Visit Me</tspan></textPath>
                    </text>
                    </svg>
</div>

2 Answers

To achieve the rotation of the circle with the text without horizontal displacements, you need to find the correct center of rotation

To do this, I wrapped path and text in a group tag <g> and using the JS method getBBox() calculated the center of rotation

let bb = circ.getBBox();

console.log(bb.x + bb.width / 2)
console.log(bb.y + bb.height / 2)

We got the coordinates x ~= 564.2px y ~=359.1px

Substitute these values into the values of the animation command animateTransform

Please open full screen
Animation will start after clicking.

If you want to start the animation without clicking, instead of begin ="svg1.click" write begin ="0s"

;
  let bb = circ.getBBox();

console.log(bb.x + bb.width / 2);
console.log(bb.y + bb.height / 2);
;
body {
  background-color: black;
}

.rotate {
 
  opacity: 1;
  width: 1400px;
  position: absolute;
 }

.rotate:hover {
  opacity: 1;
  transition: 0.4s
}
<div class="rotate" >
  <?xml version="1.0" encoding="utf-8"?>
  <!-- Generator: Adobe Illustrator 24.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
  <svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 500" >
                    <style type="text/css">
                        .st0{fill:none;}
                    </style>
                    <g id="circ"  >
                    <path id="SVGID_x5F_1_x5F_" class="st0" d="M638,358.5c0,40.59-32.91,73.5-73.5,73.5S491,399.09,491,358.5s32.91-73.5,73.5-73.5
                        S638,317.91,638,358.5z"/>
                    <text><textPath  xlink:href="#SVGID_x5F_1_x5F_" startOffset="0%">
                    <tspan  style="fill:#FFFFFF; font-family:'fatboy-slim'; font-size:40px; letter-spacing: 0px;">Visit Me Visit Me Visit Me</tspan></textPath>
                    </text>
                    </g> 
                    <animateTransform
                      xlink:href="#circ"
                      attributeName="transform"
                      type="rotate"
                      begin="svg1.click" dur="4s"
                      values="
                       0 564.2 359.1;
                       360 564.2 359.1"
                       repeatCount="indefinite"
                       calcMode="linear"
                       />
                    </svg>
</div>

Upd

As a bonus

Forward-backward rotation on repeated clicks

Add a second animation that rotates the caption in the opposite direction

The JS script switches from the first clockwise rotation animation to the second counterclockwise rotation animation:

var svg_1 = document.getElementById("svg1"),
  forward = document.getElementById('forward'),
  back = document.getElementById("back");

let flag = true;

svg_1.addEventListener('click', function() {
  if (flag == true) {
    forward.beginElement();
    flag = false;
  } else {
    back.beginElement();
    flag = true;
  }
});
body {
  background-color: black;
}

.rotate {
 
  opacity: 1;
  width: 1400px;
  position: absolute;
 }

.rotate:hover {
  opacity: 1;
  transition: 0.4s
}
<div class="rotate" >
  <?xml version="1.0" encoding="utf-8"?>
  <!-- Generator: Adobe Illustrator 24.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
  <svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 500" >
                    <style type="text/css">
                        .st0{fill:none;}
                    </style>
                    <g id="circ"  >
                    <path id="SVGID_x5F_1_x5F_" class="st0" d="M638,358.5c0,40.59-32.91,73.5-73.5,73.5S491,399.09,491,358.5s32.91-73.5,73.5-73.5
                        S638,317.91,638,358.5z"/>
                    <text><textPath  xlink:href="#SVGID_x5F_1_x5F_" startOffset="0%">
                    <tspan  style="fill:#FFFFFF; font-family:'fatboy-slim'; font-size:40px; letter-spacing: 0px;">Visit Me Visit Me Visit Me</tspan></textPath>
                    </text>
                    </g> 
                    <animateTransform id="forward"
                      xlink:href="#circ"
                      attributeName="transform"
                      type="rotate"
                      begin="indefinite"
                      dur="4s"
                      values="
                       0 564.2 359.1;
                       360 564.2 359.1"
                       repeatCount="indefinite"
                       calcMode="linear"
                       />  
                        <animateTransform id="back"
                              xlink:href="#circ"
                              attributeName="transform"
                              type="rotate"
                              begin="indefinite"
                              dur="4s"
                              values="
                               360 564.2 359.1;
                               0 564.2 359.1 "
                               repeatCount="indefinite"
                               calcMode="linear"
                               />
                    </svg>
</div>

Here's small snippet that might help add some clarification/value. Possibly a case of the SVG not being centred in the container div with the class .rotate. Below are two examples indicating the behaviour when the SVG is centred and is not centred in the container. Alternatively, you can rotate the SVG if your intended rotation point is the centre of the path/SVG. The grey square divs in this example serve as the containers. Press the Run code snippet button below to see the results (not supported in mobile app):

#Container_1,
#Container_2 {
  position: absolute;
  --Size: 120px;
  width: var(--Size);
  height: var(--Size);
  top: calc(50% - var(--Size)/2);
  background: rgba(0, 0, 0, 0.02);
}

#Container_1 {
  left: calc(30% - var(--Size)/2);
}

#Container_2 {
  left: calc(70% - var(--Size)/2);
}

#Instagram_SVG_1 {
  position: relative;
  --Size: 50%;
  width: var(--Size);
  height: var(--Size);
  top: calc(50% - var(--Size)/2);
  left: calc(50% - var(--Size)/2);
}

#Instagram_SVG_2 {
  position: relative;
  --Size: 50%;
  width: var(--Size);
  height: var(--Size);
  top: calc(70% - var(--Size)/2);
  left: calc(70% - var(--Size)/2);
}

.rotate {
  animation: rotation 8s infinite linear;
}

@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
<div id="Container_1" class="rotate">
  <svg id="Instagram_SVG_1" viewBox="0 0 267 267" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="0.879301" y="0.472702" width="265.906" height="265.906" rx="65" fill="url(#paint0_radial)"/>
  <rect x="0.879301" y="0.472702" width="265.906" height="265.906" rx="65" fill="url(#paint1_radial)"/>
  <rect x="0.879301" y="0.472672" width="265.906" height="265.906" rx="65" fill="url(#paint2_radial)" fill-opacity="0.5"/>
  <g filter="url(#filter0_d)">
  <rect x="45.0938" y="44.6872" width="177.478" height="177.478" rx="51" stroke="white" stroke-width="18"/>
  </g>
  <g filter="url(#filter1_d)">
  <circle cx="133.833" cy="133.426" r="41.5422" stroke="white" stroke-width="18"/>
  </g>
  <g filter="url(#filter2_d)">
  <circle cx="185.375" cy="80.8837" r="12.1226" fill="white"/>
  </g>
  <defs>
  <filter id="filter0_d" x="34.0938" y="33.6872" width="199.478" height="199.478" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  <feFlood flood-opacity="0" result="BackgroundImageFix"/>
  <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  <feOffset/>
  <feGaussianBlur stdDeviation="1"/>
  <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
  <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
  <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
  </filter>
  <filter id="filter1_d" x="81.2904" y="80.8837" width="105.084" height="105.084" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  <feFlood flood-opacity="0" result="BackgroundImageFix"/>
  <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  <feOffset/>
  <feGaussianBlur stdDeviation="1"/>
  <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
  <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
  <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
  </filter>
  <filter id="filter2_d" x="171.252" y="66.7611" width="28.2452" height="28.2452" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  <feFlood flood-opacity="0" result="BackgroundImageFix"/>
  <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  <feOffset/>
  <feGaussianBlur stdDeviation="1"/>
  <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
  <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
  <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
  </filter>
  <radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.7099 294.541) rotate(-71.1422) scale(559.895)">
  <stop offset="0.0280936" stop-color="#FEDC7D"/>
  <stop offset="0.18015" stop-color="#FE712B"/>
  <stop offset="0.285012" stop-color="#F9214D"/>
  <stop offset="0.370129" stop-color="#F1176C"/>
  <stop offset="0.472076" stop-color="#B624B7"/>
  <stop offset="0.713962" stop-color="#3A49F1"/>
  </radialGradient>
  <radialGradient id="paint1_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.7099 294.541) rotate(-71.1422) scale(559.895)">
  <stop offset="0.0280936" stop-color="#FEDC7D"/>
  <stop offset="0.18015" stop-color="#FE712B"/>
  <stop offset="0.285012" stop-color="#F9214D"/>
  <stop offset="0.370129" stop-color="#F1176C"/>
  <stop offset="0.472076" stop-color="#B624B7"/>
  <stop offset="0.713962" stop-color="#3A49F1"/>
  </radialGradient>
  <radialGradient id="paint2_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(144.575 242.525) rotate(-112.874) scale(262.711)">
  <stop offset="0.470143" stop-color="#F1176C" stop-opacity="0"/>
  <stop offset="0.928326" stop-color="#3A49F1"/>
  </radialGradient>
  </defs>
  </svg>
</div>


<div id="Container_2" class="rotate">
  <svg id="Instagram_SVG_2" viewBox="0 0 267 267" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="0.879301" y="0.472702" width="265.906" height="265.906" rx="65" fill="url(#paint0_radial)"/>
  <rect x="0.879301" y="0.472702" width="265.906" height="265.906" rx="65" fill="url(#paint1_radial)"/>
  <rect x="0.879301" y="0.472672" width="265.906" height="265.906" rx="65" fill="url(#paint2_radial)" fill-opacity="0.5"/>
  <g filter="url(#filter0_d)">
  <rect x="45.0938" y="44.6872" width="177.478" height="177.478" rx="51" stroke="white" stroke-width="18"/>
  </g>
  <g filter="url(#filter1_d)">
  <circle cx="133.833" cy="133.426" r="41.5422" stroke="white" stroke-width="18"/>
  </g>
  <g filter="url(#filter2_d)">
  <circle cx="185.375" cy="80.8837" r="12.1226" fill="white"/>
  </g>
  <defs>
  <filter id="filter0_d" x="34.0938" y="33.6872" width="199.478" height="199.478" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  <feFlood flood-opacity="0" result="BackgroundImageFix"/>
  <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  <feOffset/>
  <feGaussianBlur stdDeviation="1"/>
  <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
  <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
  <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
  </filter>
  <filter id="filter1_d" x="81.2904" y="80.8837" width="105.084" height="105.084" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  <feFlood flood-opacity="0" result="BackgroundImageFix"/>
  <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  <feOffset/>
  <feGaussianBlur stdDeviation="1"/>
  <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
  <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
  <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
  </filter>
  <filter id="filter2_d" x="171.252" y="66.7611" width="28.2452" height="28.2452" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  <feFlood flood-opacity="0" result="BackgroundImageFix"/>
  <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  <feOffset/>
  <feGaussianBlur stdDeviation="1"/>
  <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
  <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
  <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
  </filter>
  <radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.7099 294.541) rotate(-71.1422) scale(559.895)">
  <stop offset="0.0280936" stop-color="#FEDC7D"/>
  <stop offset="0.18015" stop-color="#FE712B"/>
  <stop offset="0.285012" stop-color="#F9214D"/>
  <stop offset="0.370129" stop-color="#F1176C"/>
  <stop offset="0.472076" stop-color="#B624B7"/>
  <stop offset="0.713962" stop-color="#3A49F1"/>
  </radialGradient>
  <radialGradient id="paint1_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.7099 294.541) rotate(-71.1422) scale(559.895)">
  <stop offset="0.0280936" stop-color="#FEDC7D"/>
  <stop offset="0.18015" stop-color="#FE712B"/>
  <stop offset="0.285012" stop-color="#F9214D"/>
  <stop offset="0.370129" stop-color="#F1176C"/>
  <stop offset="0.472076" stop-color="#B624B7"/>
  <stop offset="0.713962" stop-color="#3A49F1"/>
  </radialGradient>
  <radialGradient id="paint2_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(144.575 242.525) rotate(-112.874) scale(262.711)">
  <stop offset="0.470143" stop-color="#F1176C" stop-opacity="0"/>
  <stop offset="0.928326" stop-color="#3A49F1"/>
  </radialGradient>
  </defs>
  </svg>
</div>

Related