Reputation: 437
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);
})();
Upvotes: 3
Views: 798
Reputation: 14545
Pure SVG solution and some JS for percent output
As in this question
To solve, you need to combine two animations:
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.sstatic.net/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>
Upvotes: 3
Reputation: 101810
All you need to do is rotate the <circle>
, with the icon/image, by the same amount in the opposite direction.
$complete_circle_circ = $('.case_progress__prog circle'),
...
$complete_circle_circ.css({'transition': 'transform 2s',
'transform-box': 'fill-box',
'transform-origin': '50% 50%'});
$complete_circle_circ.attr("transform", 'rotate(' + (-$rotation) + ')');
BTW, I also fixed your percent->rotation calculation.
$rotation = $percent * 360 / 100;
(function(){
var $wrapper = $('.case_progress_wrapper'),
$progress = $('.case_progress__value'),
$circle_path = $('#case_progress__path'),
$complete_circle = $('.case_progress__prog'),
$complete_circle_circ = $('.case_progress__prog circle'),
$percent = $wrapper.data('percent'),
$rotation = $percent * 360 / 100;
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(' + $rotation + ',' + $circle_path.attr('cx') + ',' + $circle_path.attr('cy') +')');
$complete_circle_circ.css({'transition': 'transform 2s', 'transform-box': 'fill-box', 'transform-origin': '50% 50%'});
$complete_circle_circ.attr("transform", 'rotate(' + (-$rotation) + ')');
setTimeout(function () {
$progress.css('transition', 'none');
$complete_circle.css('transition', 'all 2s');
}, 2000);
}, 1000);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
```
<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">
<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>
```
```
Upvotes: 1