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); })();
Advertisement
Answer
Pure SVG solution and some JS for percent output
As in this question
To solve, you need to combine two animations:
- Painting of the arc from the beginning to the end
- 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>