Reputation: 1535
Im trying to create a circle animation that follows a rotation of something else... Im havin' a hard time creating the gradient circle animation: https://jsfiddle.net/rmtu913c/
Animation code for the circle is:
.circular-loader {
height: 116%;
width: 121%;
animation: rotate 5s ease-in-out infinite;
transform-origin: center center;
position: absolute;
top: 0;
left: 0;
margin: auto;
}
My problem as of now is that the gradient is always visible, and now im just rotating the svg container, and I somehow need to create a "mask" of some sort to achieve the wanted effect...
What Im trying to achieve is this: Circle Animation Illustrated
I hope someone has an idea om how to achieve this... I've been trying all kindda different ways for about 7 hours, and still no luck :( :(
Upvotes: 0
Views: 911
Reputation: 101820
It's pretty easy to produce a version of the semicircular gradient that uses a linear gradient to approximate an arc gradient.
body {
background-color: #2f2f2f;
}
path {
animation: rot 1.5s linear infinite;
}
@keyframes rot {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<svg width="300" height="300">
<defs>
<linearGradient id="bluefade" x1="0" y1="1" x2="0" y2="0">
<stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
<stop offset="1" stop-color="#12b1db" stop-opacity="1"/>
</linearGradient>
</defs>
<g transform="translate(150,150)">
<path d="M 0,-120 A 120,120 0 0 0 0,120"
fill="none" stroke="url(#bluefade)" stroke-width="25"/>
</g>
</svg>
But your one is not a full semicircle the whole time. It appears to grow from zero length at 12 o'clock and doesn't get to the full 180deg length until 6 o'clock. That's a bit trickier.
I think you are going to need to use Javascript to modify the gradient settings (position) so it is appropriate for each progress percentage. That'll require some trigonometry to calculate the correct position.
var progress = document.getElementById("progress");
var bluefade = document.getElementById("bluefade");
var RADIUS = 120;
function setProgress(percent)
{
// Rotation of our semicircular disc representing the progress
var rotateDeg = (percent * 360) / 100;
// Calculate position of trailing position of arc segment.
// At progress=0%, it will be at the same position as the leading point
// (0,-120),, a zero degree arc segment.
// At 25% (3 o'clock) it will be at the 9 o'clock position of the semicircle.
// At 50% (6 o'clock) it will be at the other side of the semicircle (ie 180deg
// or (0,120). At >50% it doesn't move from that position.
// This is also made the trailing point of the gradient.
var trailAngleRad = Math.min(Math.PI, (percent * Math.PI * 2)/100);
var x1 = -Math.sin(trailAngleRad) * RADIUS;
var y1 = -Math.cos(trailAngleRad) * RADIUS;
// Update the path
progress.setAttribute("d", "M 0,-120 A 120,120 0 0 0 " + x1 + "," + y1);
// Update the gradient
bluefade.x1.baseVal.value = x1;
bluefade.y1.baseVal.value = y1;
progress.setAttribute("transform", "rotate(" + rotateDeg + ")");
}
setProgress(20);
body {
background-color: #2f2f2f;
}
<svg width="300" height="300">
<defs>
<linearGradient id="bluefade"
gradientUnits="userSpaceOnUse"
x1="0" y1="120" x2="0" y2="-120">
<stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
<stop offset="1" stop-color="#12b1db" stop-opacity="1"/>
</linearGradient>
</defs>
<g transform="translate(150,150)">
<path id="progress" d="M 0,-120 A 120,120 0 0 0 0,120"
fill="none" stroke="url(#bluefade)" stroke-width="25"/>
</g>
</svg>
Or in animated form here:
var progress = document.getElementById("progress");
var bluefade = document.getElementById("bluefade");
var RADIUS = 120;
function setProgress(percent)
{
// Rotation of our semicircular disc representing the progress
var rotateDeg = (percent * 360) / 100;
// Calculate position of trailing position of arc segment.
// At progress=0%, it will be at the same position as the leading point
// (0,-120),, a zero degree arc segment.
// At 25% (3 o'clock) it will be at the 9 o'clock position of the semicircle.
// At 50% (6 o'clock) it will be at the other side of the semicircle (ie 180deg
// or (0,120). At >50% it doesn't move from that position.
// This is also made the trailing point of the gradient.
var trailAngleRad = Math.min(Math.PI, (percent * Math.PI * 2)/100);
var x1 = -Math.sin(trailAngleRad) * RADIUS;
var y1 = -Math.cos(trailAngleRad) * RADIUS;
// Update the path
progress.setAttribute("d", "M 0,-120 A 120,120 0 0 0 " + x1 + "," + y1);
// Update the gradient
bluefade.x1.baseVal.value = x1;
bluefade.y1.baseVal.value = y1;
progress.setAttribute("transform", "rotate(" + rotateDeg + ")");
}
var start = null;
function step(timestamp) {
if (!start) start = timestamp;
var percent = ((timestamp - start)/50) % 100;
setProgress(percent);
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
body {
background-color: #2f2f2f;
}
<svg width="300" height="300">
<defs>
<linearGradient id="bluefade"
gradientUnits="userSpaceOnUse"
x1="0" y1="120" x2="0" y2="-120">
<stop offset="0.05" stop-color="#fff" stop-opacity="0"/>
<stop offset="1" stop-color="#12b1db" stop-opacity="1"/>
</linearGradient>
</defs>
<g transform="translate(150,150)">
<path id="progress" d="M 0,-120 A 120,120 0 0 0 0,120"
fill="none" stroke="url(#bluefade)" stroke-width="25"/>
</g>
</svg>
Upvotes: 2