SVG progress circle image rotation orientation

Tags: , , ,



I am trying to create a circular progress bar (as seen in the image below). The progression is based on percentages and will move round the circle to that percentage. I have the progression moving round but the icon which moves with it needs to have the correct orientation. as the image bellow the images bottom is facing the centre when it should be facing the bottom of the screen. the images needs to move along with the bar.

<div class="case_progress_wrapper" data-percent="80">
 <svg class="case_progress_circle" height="100%" width="100%" viewBox="0 0 140 140">
  <circle id="case_progress__path" cx="70" cy="70" r="54" fill="none" stroke="#EBEDF8" stroke-width="1" />
  <circle class="case_progress__value" cx="70" cy="70" r="54" fill="none" stroke="#f00" stroke-width="6" />
  <circle class="case_progress__inner" cx="70" cy="70" r="44" fill="#fff" stroke="#fff" stroke-width="1" />
  <circle class="case_progress__start" cx="124" cy="63" r="3" fill="#fff" stroke="#fff" stroke-width="1" />
  <g id='case_progress__prog_fill' class="case_progress__prog" viewBox="0 0 60 60">
    <circle fill="url(#image)" cx="124" cy="63" r="8" stroke="#fff" stroke-width="1" />
  </g>
  <defs>
    <pattern id="image" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 60 60">
      <image x="0%" y="0%" width="60" height="60" xlink:href="https://via.placeholder.com/150x150"></image>
    </pattern>
  </defs>
 </svg>
</div>
   

   
(function(){
            var $wrapper = $('.case_progress_wrapper'),
                $progress = $('.case_progress__value'),
                $circle_path = $('#case_progress__path'),
                $complete_circle = $('.case_progress__prog'),
                $percent = $wrapper.data('percent');

            setTimeout(function () {
                $progress.css('transition', 'all 2s');
                $progress.css('stroke-dashoffset', 'calc(339.292 - (' + $percent + ' * 339.292 / 100))');
                $complete_circle.css('transition', 'all 2s');
                $complete_circle.attr("transform", 'rotate(' + (360 - ($percent - 25)) + ',' + $circle_path.attr('cx') + ',' + $circle_path.attr('cy') +')');

                setTimeout(function () {
                    $progress.css('transition', 'none');
                    $complete_circle.css('transition', 'all 2s');
                }, 2000);

            }, 1000);

        })();

this is what I currently have

Answer

Pure SVG solution and some JS for percent output

enter image description here

As in this question

To solve, you need to combine two animations:

  1. Painting of the arc from the beginning to the end
  2. Animation of movement of a circle with an image inside

Set the same time for both animations

Please read the comments in the code.

var count = $(('#count'));
$({ Counter: 0 }).animate({ Counter: count.text() }, {
  duration: 10000,
  easing: 'linear',
  step: function () {
    count.text(Math.ceil(this.Counter)+ "%");
  }
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="case_progress_wrapper" data-percent="80" style="width:50vw; height:50vh;">
 <svg class="case_progress_circle"  viewBox="0 0 140 140">
<defs>
    <pattern id="image" x="0%" y="0%" height="100%" width="100%" viewBox="1 0 58 58">
      <image  x="0%" y="0%" width="60" height="60" xlink:href="https://i.stack.imgur.com/uQMJ3.jpg"></image>
    </pattern>
  </defs>
 <rect width="100%" height="100%" fill="#87CEEB" />
 <g transform="rotate(-90 70 70)" >  
    <!-- Track for rotating a circle with an image -->
 <path id="case_progress__path"       
     style="fill:none;stroke:#ebedf8;stroke-width:1"
     d="M 124,70 A 54,54 0 0 1 70,124 54,54 0 0 1 16,70 54,54 0 0 1 70,16 54,54 0 0 1 124,70 Z"/>
  
   <!-- Circle for the growth of the red progress bar -->
 <circle  
  class="case_progress__value" stroke-dashoffset="339.5" stroke-dasharray="339.5" cx="70" cy="70" r="54" fill="none" stroke="#f00" stroke-width="6" >
     <!-- Bar progress animation -->
   <animate attributeName="stroke-dashoffset" begin="0s" dur="10s" values="339.5;0" fill="freeze" /> 
    </circle> 
 <!-- Starting point -->
<circle class="case_progress__start" cx="124" cy="70" r="3" fill="#fff" stroke="#fff" stroke-width="1" />
  <g id='case_progress__prog_fill' class="case_progress__prog" viewBox="1 0 58 58">
  <circle transform="rotate(90 0 0)" fill="url(#image)" cx="0" cy="0"  r="8" stroke-width="0.25" stroke="#fff"   > 
      <!-- Icon rotation animation -->
        <animateMotion begin="0s" dur="10s" fill="freeze"   >
      <mpath xlink:href="#case_progress__path" /> 
      </animateMotion> 
  </circle>
  </g>  
    </g>

 <circle class="case_progress__inner" cx="70" cy="70" r="44" fill="#fff" stroke="#fff" stroke-width="1" />
  <text id="count" x="50%" y="50%" fill="red" text-anchor="middle" dy="7" font-size="20">100%</text>
 </svg>
</div> 


Source: stackoverflow