I'm struggling to find a way to rotate this SVG mask so that it rotates from within the center. In other words, I'm aiming for a spinning effect that will be on infinite loop. Also, I can't figure out why it will not rotate in Firefox. Any ideas?
Here's the JSFiddle
HTML:
<body class="home">
<svg preserveAspectRatio="xMidYMid slice">
<svg version="1.1" id="first-ring" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100%" height="100%" xml:space="preserve">
<mask id="mask" maskUnits="userSpaceOnUse">
<rect x="0" y="0" width="100%" height="100%"/>
<svg version="1.1" baseProfile="tiny" class="first-ring" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 241.5 242" xml:space="preserve">
<g class ="first-ring-path">
<g>
<g>
<path d="M118.4,237.5c-8.5,0-16.9-0.9-25.1-2.7c-2.8-0.6-4.6-3.4-3.9-6.2c0.6-2.8,3.4-4.5,6.2-3.9
c7.5,1.6,15.2,2.5,22.9,2.5c20.7,0,40.7-6,58-17.3c2.4-1.6,5.6-0.9,7.2,1.5c1.6,2.4,0.9,5.6-1.5,7.2
C163.1,230.9,141.1,237.5,118.4,237.5z"/>
</g>
<g>
<path d="M192.5,209.2c-1.4,0-2.8-0.6-3.9-1.7c-1.9-2.1-1.7-5.4,0.4-7.3c3.9-3.5,7.5-7.3,10.9-11.3
c1.8-2.2,5.1-2.5,7.3-0.7s2.5,5.1,0.7,7.3c-3.6,4.4-7.7,8.6-11.9,12.4C195,208.7,193.7,209.2,192.5,209.2z"/>
</g>
<g>
<path d="M214.6,181.9c-0.9,0-1.8-0.2-2.6-0.7c-2.5-1.4-3.3-4.6-1.9-7.1c9.3-16,14.1-34.3,14.1-52.9
c0-4.9-0.3-9.8-1-14.5c-0.4-2.8,1.6-5.4,4.4-5.8c2.8-0.4,5.4,1.6,5.8,4.4c0.7,5.2,1.1,10.6,1.1,15.9c0,20.4-5.4,40.5-15.5,58.1
C218.1,181,216.4,181.9,214.6,181.9z"/>
</g>
<g>
<path d="M224.7,94.1c-2.2,0-4.3-1.4-4.9-3.7c-2.3-7.7-5.6-15.1-9.6-22.1c-1.4-2.5-0.6-5.6,1.9-7.1
c2.5-1.4,5.6-0.6,7.1,1.9c4.4,7.7,8,15.8,10.5,24.2c0.8,2.7-0.7,5.6-3.4,6.4C225.7,94,225.2,94.1,224.7,94.1z"/>
</g>
<g>
<path d="M206.4,58.7c-1.5,0-3.1-0.7-4.1-2c-10.9-14.2-25.3-25.4-41.7-32.5c-2.6-1.1-3.8-4.2-2.7-6.8
s4.2-3.8,6.8-2.7c17.9,7.8,33.7,20.2,45.7,35.7c1.7,2.3,1.3,5.5-0.9,7.2C208.6,58.3,207.5,58.7,206.4,58.7z"/>
</g>
<g>
<path d="M41,46.7c-1.3,0-2.7-0.5-3.7-1.6c-2-2-1.9-5.3,0.1-7.3C59.2,16.6,88,5,118.4,5c1.6,0,3.2,0,4.7,0.1
c2.9,0.1,5.1,2.5,5,5.4c-0.1,2.9-2.5,5.1-5.4,5c-1.4-0.1-2.9-0.1-4.3-0.1c-27.7,0-53.9,10.6-73.7,29.9
C43.6,46.2,42.3,46.7,41,46.7z"/>
</g>
<g>
<path d="M7.5,119c-0.1,0-0.2,0-0.4,0c-2.8-0.2-5-2.7-4.8-5.5c0.3-4,0.8-8.1,1.5-12.1C6,88.3,10.5,75.7,17,64.2
c1.4-2.5,4.6-3.4,7-2c2.5,1.4,3.4,4.6,2,7c-5.9,10.5-10,21.9-12.1,33.9c-0.6,3.6-1.1,7.4-1.3,11C12.4,116.9,10.2,119,7.5,119z"/>
</g>
<g>
<path d="M58.6,220c-1,0-1.9-0.3-2.8-0.8c-26.2-16.7-44.8-43.7-51.2-74c-0.6-2.8,1.2-5.5,4-6.1s5.5,1.2,6.1,4
c5.8,27.6,22.8,52.1,46.6,67.4c2.4,1.5,3.1,4.7,1.6,7.1C61.9,219.2,60.3,220,58.6,220z"/>
</g>
</g>
</g>
</svg>
</mask>
</svg>
<rect id="rect" mask="url(#mask)" x="0" y="0" width="5000px" height="5000px"/>
</svg>
</body>
CSS:
html{
height: 100%;
overflow:hidden;
font-weight:100;
}
body {
height: 100%;
overflow:hidden;
}
svg {
width: 100%;
height: 100%;
overflow:hidden;
}
svg mask rect {
fill: rgba(255, 255, 255, 0.6);
}
svg > rect {
fill: white;
// -webkit-mask: url(#mask);
// -moz-mask: url(#mask);
// mask: url(#mask);
}
.first-ring-path{
-moz-animation:spin 20s infinite linear;
-webkit-animation:spin 20s infinite linear;
animation:spin 20s infinite linear;
}
#-moz-keyframes spin {
0% { -moz-transform:rotate(0deg); }
100% { -moz-transform:rotate(360deg); }
}
#-moz-keyframes spinoff {
0% { -moz-transform:rotate(0deg); }
100% { -moz-transform:rotate(-360deg); }
}
#-webkit-keyframes spin {
0% { -webkit-transform:rotate(0deg); }
100% { -webkit-transform:rotate(360deg); }
}
#-webkit-keyframes spinoff {
0% { -webkit-transform:rotate(0deg); }
100% { -webkit-transform:rotate(-360deg); }
}
Say I just posted the same coding to a SMIL animation issue. Only 7 liners, both are based on a old solution: How to Keep Text Orientation....
Edit: Tested on latest FF v47 (June2016)
var myPath = document.getElementById('pathRotate');
var i = 0;
var intervalID = window.setInterval(myCallback, 30);
function myCallback() {
// Rotate the square by a small amount.
if (i == 360) { i = 0}
myPath.setAttribute("transform", "rotate(" + i + ", 121,121)");
++i;
}
body {
background-color: red;
}
.home {
background-image: url('../images/ontocore_home_background.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed;
background-repeat: no-repeat;
}
.home-overlay {
height: 4000;
background-image: url('../images/ontocore_home_overlay.png');
background-size: cover;
background-position: center;
background-attachment: fixed;
background-repeat: no-repeat;
}
svg {
width: 100%;
height: 100%;
overflow:hidden;
}
svg mask rect {
fill: rgba(255, 255, 255, 0.6);
}
svg > rect {
fill: white;
// -webkit-mask: url(#mask);
// -moz-mask: url(#mask);
// mask: url(#mask);
}
<body class="home">
<svg preserveAspectRatio="xMidYMid slice">
<svg version="1.1" id="first-ring" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="100%" height="100%" xml:space="preserve">
<mask id="mask" maskUnits="userSpaceOnUse">
<rect x="0" y="0" width="100%" height="100%"/>
<svg version="1.1" baseProfile="tiny" class="first-ring" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 241.5 242" xml:space="preserve">
<g id="pathRotate" class ="first-ring-path">
<g>
<g>
<path d="M118.4,237.5c-8.5,0-16.9-0.9-25.1-2.7c-2.8-0.6-4.6-3.4-3.9-6.2c0.6-2.8,3.4-4.5,6.2-3.9
c7.5,1.6,15.2,2.5,22.9,2.5c20.7,0,40.7-6,58-17.3c2.4-1.6,5.6-0.9,7.2,1.5c1.6,2.4,0.9,5.6-1.5,7.2
C163.1,230.9,141.1,237.5,118.4,237.5z"/>
</g>
<g>
<path d="M192.5,209.2c-1.4,0-2.8-0.6-3.9-1.7c-1.9-2.1-1.7-5.4,0.4-7.3c3.9-3.5,7.5-7.3,10.9-11.3
c1.8-2.2,5.1-2.5,7.3-0.7s2.5,5.1,0.7,7.3c-3.6,4.4-7.7,8.6-11.9,12.4C195,208.7,193.7,209.2,192.5,209.2z"/>
</g>
<g>
<path d="M214.6,181.9c-0.9,0-1.8-0.2-2.6-0.7c-2.5-1.4-3.3-4.6-1.9-7.1c9.3-16,14.1-34.3,14.1-52.9
c0-4.9-0.3-9.8-1-14.5c-0.4-2.8,1.6-5.4,4.4-5.8c2.8-0.4,5.4,1.6,5.8,4.4c0.7,5.2,1.1,10.6,1.1,15.9c0,20.4-5.4,40.5-15.5,58.1
C218.1,181,216.4,181.9,214.6,181.9z"/>
</g>
<g>
<path d="M224.7,94.1c-2.2,0-4.3-1.4-4.9-3.7c-2.3-7.7-5.6-15.1-9.6-22.1c-1.4-2.5-0.6-5.6,1.9-7.1
c2.5-1.4,5.6-0.6,7.1,1.9c4.4,7.7,8,15.8,10.5,24.2c0.8,2.7-0.7,5.6-3.4,6.4C225.7,94,225.2,94.1,224.7,94.1z"/>
</g>
<g>
<path d="M206.4,58.7c-1.5,0-3.1-0.7-4.1-2c-10.9-14.2-25.3-25.4-41.7-32.5c-2.6-1.1-3.8-4.2-2.7-6.8
s4.2-3.8,6.8-2.7c17.9,7.8,33.7,20.2,45.7,35.7c1.7,2.3,1.3,5.5-0.9,7.2C208.6,58.3,207.5,58.7,206.4,58.7z"/>
</g>
<g>
<path d="M41,46.7c-1.3,0-2.7-0.5-3.7-1.6c-2-2-1.9-5.3,0.1-7.3C59.2,16.6,88,5,118.4,5c1.6,0,3.2,0,4.7,0.1
c2.9,0.1,5.1,2.5,5,5.4c-0.1,2.9-2.5,5.1-5.4,5c-1.4-0.1-2.9-0.1-4.3-0.1c-27.7,0-53.9,10.6-73.7,29.9
C43.6,46.2,42.3,46.7,41,46.7z"/>
</g>
<g>
<path d="M7.5,119c-0.1,0-0.2,0-0.4,0c-2.8-0.2-5-2.7-4.8-5.5c0.3-4,0.8-8.1,1.5-12.1C6,88.3,10.5,75.7,17,64.2
c1.4-2.5,4.6-3.4,7-2c2.5,1.4,3.4,4.6,2,7c-5.9,10.5-10,21.9-12.1,33.9c-0.6,3.6-1.1,7.4-1.3,11C12.4,116.9,10.2,119,7.5,119z"/>
</g>
<g>
<path d="M58.6,220c-1,0-1.9-0.3-2.8-0.8c-26.2-16.7-44.8-43.7-51.2-74c-0.6-2.8,1.2-5.5,4-6.1s5.5,1.2,6.1,4
c5.8,27.6,22.8,52.1,46.6,67.4c2.4,1.5,3.1,4.7,1.6,7.1C61.9,219.2,60.3,220,58.6,220z"/>
</g>
</g>
</g>
</svg>
</mask>
<
</svg>
<rect id="rect" mask="url(#mask)" x="0" y="0" width="5000px" height="5000px"/>
</svg>
</body>
for rotation from center add
transform-origin: 50% 50%;
as follows:
.first-ring-path{
-moz-animation:spin 20s infinite linear;
-webkit-animation:spin 20s infinite linear;
animation:spin 20s infinite linear;
transform-origin: 50% 50%;
}
Related
I want to move a small circle around the circumference of the big circle using only CSS.
#keyframes moveAround {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#small {
animation: moveAround 2s infinite linear;
}
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="circles">
<circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
<circle id="small" cx="60" cy="20" r="10" fill="#EF6868" />
</g>
</svg>
You must specify which coordinate the circle should rotate around. By default, this is coordinate 0,0, but you want it to orbit the center of the large circle.
In CSS, you do this with transform-origin:
#small {
transform-origin: 60px 50px;
animation: moveAround 2s infinite linear;
}
#keyframes moveAround {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="circles">
<circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
<circle id="small" cx="60" cy="20" r="10" fill="#EF6868" />
</g>
</svg>
A CSS only solution with no SVG
.box {
width: 60px;
height: 60px;
border: 20px solid #2493AB;
border-radius: 50%;
position: relative;
}
.box::before {
content: "";
width: 20px;
height: 20px;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background: #EF6868;
animation: moveAround 3s linear infinite;
}
#keyframes moveAround {
from {
transform: rotate(0deg) translate(40px);
}
to {
transform: rotate(360deg) translate(40px);
}
}
<div class="box"></div>
Pure SMIL SVG solution
To rotate the ball, use animateTransform
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="circles">
<circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
<circle id="small" cx="60" cy="20" r="10" fill="#EF6868" >
<animateTransform
attributeName="transform"
type="rotate"
begin="0s"
dur="3s"
values="
0 60 50;
360 60 50"
repeatCount="indefinite" />
</circle>
</g>
</svg>
Ball rotation with pauses between full revolutions
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="circles">
<circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
<circle id="small" cx="60" cy="20" r="10" fill="#EF6868" >
<animateTransform id="an"
attributeName="transform"
type="rotate"
begin="0s;an.end+1s"
dur="2s"
values="
0 60 50;
360 60 50"
/>
</circle>
</g>
</svg>
Back and forth rotation
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="circles">
<circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
<circle id="small" cx="60" cy="20" r="10" fill="#EF6868" >
<animateTransform
attributeName="transform"
type="rotate"
begin="0s"
dur="4s"
values="
0 60 50;
360 60 50;
360 60 50;
0 60 50;
0 60 50"
repeatCount="indefinite" />
</circle>
</g>
</svg>
Another idea with single div.
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
position: relative;
background: radial-gradient(#EF6868 0 9.5px, transparent 10.5px) 50% 0% / 20px 20px no-repeat,
radial-gradient(transparent 29px, #2493AB 30px 50px) 0 0 / 100% 100% no-repeat;
animation: animate 3s linear infinite;
}
#keyframes animate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
<div class="circle"></div>
I'm trying to get svg circular lines to rotate from the centre point of the svg. At the minute it's rotating on it's axis which is not what i want to happen. Any ideas on how to solve this?
This is my code:
#lines {
animation: antiClockwiseSpin 30s infinite linear;
animation-play-state: paused;
}
svg:hover #lines {
animation-play-state: running;
}
#keyframes antiClockwiseSpin {
0% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="435" height="435" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve">
<g fill="#000" id="lines">
<path fill="none" d="M13.528,293.508C4.551,269.306,0,243.827,0,217.778c0-28.265,5.336-55.765,15.859-81.737l1.802,0.73
C7.233,162.51,1.945,189.765,1.945,217.778c0,25.817,4.511,51.068,13.407,75.053L13.528,293.508z"/>
<path d="M217.778,435.556c-41.973,0-82.721-11.965-117.838-34.603c-34.202-22.047-61.498-53.081-78.937-89.745
c-0.231-0.485-0.025-1.065,0.46-1.296c0.484-0.233,1.065-0.025,1.296,0.46c17.284,36.337,44.337,67.095,78.235,88.946
c34.803,22.435,75.186,34.293,116.784,34.293c11.55,0,23.139-0.919,34.445-2.733c0.526-0.087,1.029,0.275,1.114,0.806
c0.085,0.53-0.276,1.029-0.806,1.114C241.123,434.629,229.431,435.556,217.778,435.556z"/>
<path fill="none" d="M269.654,429.34l-0.461-1.889c30.629-7.484,59.825-21.988,84.433-41.944l1.225,1.511
C330.021,407.152,300.56,421.787,269.654,429.34z"/>
<path d="M361.996,380.637c-0.268,0-0.534-0.11-0.726-0.325c-0.357-0.401-0.322-1.015,0.079-1.373
c45.924-40.941,72.264-99.682,72.264-161.161c0-15.731-1.701-31.424-5.054-46.646c-0.115-0.525,0.216-1.043,0.74-1.159
c0.526-0.12,1.043,0.216,1.159,0.74c3.384,15.359,5.099,31.194,5.099,47.064c0,62.033-26.576,121.303-72.914,162.612
C362.457,380.556,362.226,380.637,361.996,380.637z"/>
<path fill="none" d="M423.026,150.825c-17.539-53.8-56.571-99.477-107.089-125.319l0.886-1.731
c50.971,26.074,90.355,72.162,108.051,126.447L423.026,150.825z"/>
<path d="M28.427,113.072c-0.16,0-0.323-0.04-0.474-0.124c-0.469-0.262-0.636-0.855-0.374-1.323C66.089,42.772,138.969,0,217.778,0
c31.227,0,61.374,6.469,89.603,19.229c0.489,0.221,0.706,0.797,0.485,1.287c-0.221,0.489-0.797,0.706-1.287,0.485
C278.605,8.356,248.727,1.945,217.778,1.945c-78.106,0-150.336,42.391-188.502,110.63
C29.098,112.893,28.768,113.072,28.427,113.072z"/>
</g>
</svg>
Here's a jsfiddle: https://jsfiddle.net/alexgomy/fdkh0wzb/1/
Unlike HTML elements, the default transform-origin of SVG elements is 0 0 (top left). You need to set transform-origin: center; on #lines:
#lines {
animation: antiClockwiseSpin 30s infinite linear;
animation-play-state: paused;
transform-origin: center;
}
svg:hover #lines {
animation-play-state: running;
}
#keyframes antiClockwiseSpin {
0% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
#keyframes antiClockwiseSpin {
0% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="435" height="435" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve">
<g fill="#000" id="lines">
<path fill="none" d="M13.528,293.508C4.551,269.306,0,243.827,0,217.778c0-28.265,5.336-55.765,15.859-81.737l1.802,0.73
C7.233,162.51,1.945,189.765,1.945,217.778c0,25.817,4.511,51.068,13.407,75.053L13.528,293.508z"/>
<path d="M217.778,435.556c-41.973,0-82.721-11.965-117.838-34.603c-34.202-22.047-61.498-53.081-78.937-89.745
c-0.231-0.485-0.025-1.065,0.46-1.296c0.484-0.233,1.065-0.025,1.296,0.46c17.284,36.337,44.337,67.095,78.235,88.946
c34.803,22.435,75.186,34.293,116.784,34.293c11.55,0,23.139-0.919,34.445-2.733c0.526-0.087,1.029,0.275,1.114,0.806
c0.085,0.53-0.276,1.029-0.806,1.114C241.123,434.629,229.431,435.556,217.778,435.556z"/>
<path fill="none" d="M269.654,429.34l-0.461-1.889c30.629-7.484,59.825-21.988,84.433-41.944l1.225,1.511
C330.021,407.152,300.56,421.787,269.654,429.34z"/>
<path d="M361.996,380.637c-0.268,0-0.534-0.11-0.726-0.325c-0.357-0.401-0.322-1.015,0.079-1.373
c45.924-40.941,72.264-99.682,72.264-161.161c0-15.731-1.701-31.424-5.054-46.646c-0.115-0.525,0.216-1.043,0.74-1.159
c0.526-0.12,1.043,0.216,1.159,0.74c3.384,15.359,5.099,31.194,5.099,47.064c0,62.033-26.576,121.303-72.914,162.612
C362.457,380.556,362.226,380.637,361.996,380.637z"/>
<path fill="none" d="M423.026,150.825c-17.539-53.8-56.571-99.477-107.089-125.319l0.886-1.731
c50.971,26.074,90.355,72.162,108.051,126.447L423.026,150.825z"/>
<path d="M28.427,113.072c-0.16,0-0.323-0.04-0.474-0.124c-0.469-0.262-0.636-0.855-0.374-1.323C66.089,42.772,138.969,0,217.778,0
c31.227,0,61.374,6.469,89.603,19.229c0.489,0.221,0.706,0.797,0.485,1.287c-0.221,0.489-0.797,0.706-1.287,0.485
C278.605,8.356,248.727,1.945,217.778,1.945c-78.106,0-150.336,42.391-188.502,110.63
C29.098,112.893,28.768,113.072,28.427,113.072z"/>
</g>
</svg>
I am trying to make a svg animation, as the demo shows when I scale the charge fill of svg, it was pushed to the container's left edge.
Is it possible to keep the x,y attributes of the path in the svg? Or is my svg made impossible to animate correctly?
.svg {
width: 40%;
}
#charge {
/* animation: charge 1s ease infinite; */
transform: scaleX(0.1);
}
#keyframes charge {
0% {
transform: scaleX(0.1);
}
100% {
transform: scale(1);
}
}
<div class="svg">
<svg xmlns="http://www.w3.org/2000/svg" id="battery_1_" x="0px" y="0px" viewBox="0 0 214 100">
<polygon id="outline" points="214,22.5 200,22.5 200,0 0,0 0,100 200,100 200,77.5 214,77.5"/>
<rect id="charge" width="180" height="80" x="10" y="10" fill="#0071BC"/>
</svg>
</div>
To avoid setting pixel value on the transform-origin you can also adjust the transform-box to have the transform-origin relative to the element and not the whole SVG:
.svg {
width: 40%;
}
#charge {
transform-origin: left;
transform-box:fill-box;
animation: charge 1s ease infinite;
transform: scaleX(0.1);
}
#keyframes charge {
0% {
transform: scaleX(0.1);
}
100% {
transform: scale(1);
}
}
<div class="svg">
<svg xmlns="http://www.w3.org/2000/svg" id="battery_1_" x="0px" y="0px" viewBox="0 0 214 100">
<polygon id="outline" points="214,22.5 200,22.5 200,0 0,0 0,100 200,100 200,77.5 214,77.5"/>
<rect id="charge" width="180" height="80" x="10" y="10" fill="#0071BC"/>
</svg>
</div>
You can use the transform-origin property allows you to change the position of transforming elements. The default values are 50%, 50%, making your transforms start in the middle of the element.
.svg {
width: 40%;
}
#charge {
transform-origin: 10px;
animation: charge 1s ease infinite;
transform: scaleX(0.1);
}
#keyframes charge {
0% {
transform: scaleX(0.1);
}
100% {
transform: scale(1);
}
}
<div class="svg">
<svg xmlns="http://www.w3.org/2000/svg" id="battery_1_" x="0px" y="0px" viewBox="0 0 214 100">
<polygon id="outline" points="214,22.5 200,22.5 200,0 0,0 0,100 200,100 200,77.5 214,77.5"/>
<rect id="charge" width="180" height="80" x="10" y="10" fill="#0071BC"/>
</svg>
</div>
You can animate the width instead, to achieve the desired effect:
.svg {
width: 40%;
}
#charge {
width: 10px;
height: 80px;
animation: charge 1s ease infinite;
}
#keyframes charge {
0% {
width: 0;
}
100% {
width: 180px;
}
}
<div class="svg">
<svg xmlns="http://www.w3.org/2000/svg" id="battery_1_" x="0px" y="0px" viewBox="0 0 214 100">
<polygon id="outline" points="214,22.5 200,22.5 200,0 0,0 0,100 200,100 200,77.5 214,77.5"/>
<rect id="charge" x="10" y="10" fill="#0071BC"/>
</svg>
</div>
I want to do a animation of a wave that turns into a straight line.
What I have right now is a animation of a wave that goes from left to right see the below code. Also can this be made only using css?
body {
width: 960px;
height: 100%;
background-color: #d3d3d3;
}
/*#wave1 {
transform: translate(-260px, 200px);
}*/
#wave1 {
animation: popup 5s ease infinite;
}
#keyframes popup {
0% {
transform: translate( -500px, 0);
}
100% {
transform: translate(400px, 0);
}
}
#wave2 {
animation: popup 5s ease infinite;
}
#keyframes popup {
0% {
transform: translate( -500px, 0);
}
100% {
transform: translate(400px, 0);
}
}
#wave3 {
animation: popup 5s ease infinite;
}
#keyframes popup {
0% {
transform: translate( -500px, 0);
}
100% {
transform: translate(400px, 0);
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="960px" height="200px" viewBox="91.43 -87.5 960 200" overflow="visible" enable-background="new 91.43 -87.5 960 200" xml:space="preserve">
<defs> </defs>
<path id="wave1" fill="none" stroke="#2E2925" stroke-miterlimit="10" d="M0,24.5c28.57,0,28.57-24,57.141-24c28.57,0,28.57,24,57.141,24
c28.572,0,28.572-24,57.142-24c28.57,0,28.57,24,57.141,24c28.572,0,28.572-24,57.143-24c28.569,0,28.569,24,57.138,24
c28.57,0,28.57-24,57.14-24c28.57,0,28.57,24,57.139,24s28.569-24,57.14-24c28.57,0,28.57,24,57.14,24c28.572,0,28.572-24,57.145-24
s28.572,24,57.145,24c28.571,0,28.571-24,57.143-24c28.572,0,28.572,24,57.145,24c28.573,0,28.573-24,57.146-24
c28.571,0,28.571,24,57.143,24c28.573,0,28.573-24,57.146-24c28.573,0,28.573,24,57.146,24c28.574,0,28.574-24,57.149-24
s28.575,24,57.149,24" /> </svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" x="0px" y="0px" width="960px" height="200px" viewBox="120 -87.5 960 200" overflow="visible" enable-background="new 120 -87.5 960 200" xml:space="preserve">
<defs> </defs>
<path id="wave2" fill="none" stroke="#E74267" stroke-miterlimit="10" d="M0,0.5c14.633,0,14.633,24,29.266,24c14.632,0,14.632-24,29.265-24
c14.636,0,14.636,24,29.27,24c14.633,0,14.633-24,29.265-24c14.635,0,14.635,24,29.268,24c14.635,0,14.635-24,29.269-24
c14.633,0,14.633,24,29.267,24c14.633,0,14.633-24,29.267-24s14.634,24,29.266,24c14.635,0,14.635-24,29.269-24s14.634,24,29.268,24
s14.634-24,29.269-24c14.634,0,14.634,24,29.269,24c14.633,0,14.633-24,29.268-24c14.631,0,14.631,24,29.262,24
c14.633,0,14.633-24,29.266-24c14.632,0,14.632,24,29.266,24c14.631,0,14.631-24,29.263-24c14.634,0,14.634,24,29.266,24
c14.636,0,14.636-24,29.269-24c14.635,0,14.635,24,29.268,24s14.633-24,29.266-24s14.633,24,29.266,24s14.633-24,29.268-24
c14.633,0,14.633,24,29.266,24c14.637,0,14.637-24,29.271-24s14.635,24,29.268,24c14.635,0,14.635-24,29.27-24s14.635,24,29.27,24
s14.635-24,29.27-24s14.635,24,29.27,24s14.635-24,29.27-24c14.633,0,14.633,24,29.266,24c14.635,0,14.635-24,29.27-24
s14.635,24,29.27,24s14.635-24,29.271-24s14.637,24,29.271,24c14.639,0,14.639-24,29.275-24s14.637,24,29.273,24
c14.639,0,14.639-24,29.277-24s14.639,24,29.277,24" /> </svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="960px" height="200px" viewBox="100.641 -75.5 960 200" overflow="visible" enable-background="new 100.641 -75.5 960 200" xml:space="preserve">
<defs> </defs>
<path id="wave3" fill="none" stroke="#000000" stroke-miterlimit="10" d="M1161.282,0.5c-19.359,0-19.359,48-38.719,48
c-19.355,0-19.355-48-38.713-48c-19.355,0-19.355,48-38.715,48c-19.355,0-19.355-48-38.711-48s-19.355,48-38.711,48
c-19.354,0-19.354-48-38.707-48c-19.355,0-19.355,48-38.713,48c-19.355,0-19.355-48-38.711-48s-19.355,48-38.713,48
c-19.354,0-19.354-48-38.709-48s-19.355,48-38.709,48s-19.354-48-38.709-48c-19.354,0-19.354,48-38.709,48
c-19.354,0-19.354-48-38.709-48c-19.354,0-19.354,48-38.71,48c-19.353,0-19.353-48-38.707-48c-19.353,0-19.353,48-38.706,48
s-19.353-48-38.705-48s-19.352,48-38.704,48c-19.353,0-19.353-48-38.705-48c-19.355,0-19.355,48-38.709,48
c-19.355,0-19.355-48-38.708-48c-19.356,0-19.356,48-38.71,48s-19.354-48-38.708-48s-19.354,48-38.708,48
c-19.355,0-19.355-48-38.708-48c-19.355,0-19.355,48-38.709,48s-19.354-48-38.709-48s-19.354,48-38.709,48S19.354,0.5,0,0.5" /> </svg>
If you want the wave to flatten to a line, just can just animate its scale from 1 to 0. I don't know if that is the effect you are after though.
body {
width: 960px;
height: 100%;
background-color: #d3d3d3;
}
/*#wave1 {
transform: translate(-260px, 200px);
}*/
#wave1 {
animation: popup 5s ease infinite;
}
#keyframes popup {
0% {
transform: translate( -500px, 0) scale(1,1);
}
100% {
transform: translate(400px, 0) scale(1,0);
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="960px" height="200px" viewBox="91.43 -87.5 960 200" overflow="visible" enable-background="new 91.43 -87.5 960 200" xml:space="preserve">
<defs> </defs>
<path id="wave1" fill="none" stroke="#2E2925" stroke-miterlimit="10" d="M0,24.5c28.57,0,28.57-24,57.141-24c28.57,0,28.57,24,57.141,24
c28.572,0,28.572-24,57.142-24c28.57,0,28.57,24,57.141,24c28.572,0,28.572-24,57.143-24c28.569,0,28.569,24,57.138,24
c28.57,0,28.57-24,57.14-24c28.57,0,28.57,24,57.139,24s28.569-24,57.14-24c28.57,0,28.57,24,57.14,24c28.572,0,28.572-24,57.145-24
s28.572,24,57.145,24c28.571,0,28.571-24,57.143-24c28.572,0,28.572,24,57.145,24c28.573,0,28.573-24,57.146-24
c28.571,0,28.571,24,57.143,24c28.573,0,28.573-24,57.146-24c28.573,0,28.573,24,57.146,24c28.574,0,28.574-24,57.149-24
s28.575,24,57.149,24" /> </svg>
I have a requirement where I need to load js files dynamically and show the progress of loading files through a SVG icon. The SVG icon will act as progress bar where it fills with a color from bottom to top, linearly.
Here is the codepen
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
<path fill="transparent" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</svg>
I am planning to make this icon independent such that I will only pass the percentage value dynamically.
I somehow able to get the animation done but unable to keep the border or outline of the svg. Here is the code.
#progressMove {
transition: .3s y;
}
#progressMove:hover {
y: 60%;
}
<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
<defs>
<mask id="bubbleKenseo">
<path fill="red" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</mask>
</defs>
<g x="0" y="0" width="79.36px" height="93.844px" mask="url(#bubbleKenseo)" height="100">
<rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" />
</g>
</svg>
So, the problems I have are:
Unable to maintain the border to the SVG
Whatever the color I add is having some kind of opacity which I am unable to remove.
Edit: Browser compatibility: IE11+, chrome, safari and firefox
PS: I don't want to use SMIL animations.
CHROME/SAFARI SOLUTION
Using the CSS property transform and counter-increment you can achieve the fill and number increment.
jsFiddle
CODE SNIPPET
for (var i = 0; i < 100; i++) {
setTimeout(function() {
$(".progress-container p").append("<span>");
}, i * 20);
}
pattern #progressMove {
transform: translateY(100%);
color: purple;
animation: progressBar 2s steps(100, end) forwards;
}
#keyframes progressBar {
to {
transform: translateY(0);
}
}
.progress-container {
margin: 0;
display: inline-block;
position: relative;
counter-reset: progress;
}
.progress-container figcaption {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-40%, -50%);
}
.progress-container p {
margin: 0;
font-weight: bold;
}
.progress-container span {
counter-increment: progress;
}
.progress-container p::after {
content: counter(progress)"%";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<figure class="progress-container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
<pattern id="progress" x="0" y="0" width="79.36" height="93.844" patternUnits="userSpaceOnUse">
<rect id="progressMove" x="0" y="0" width="100%" height="100%" stroke="none" fill="currentColor" />
</pattern>
<path fill="url(#progress)" stroke="#000" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</svg>
<figcaption>
<p>
</p>
</figcaption>
</figure>
Note:
Will update if I can give a better solution to cover browser support.
EDIT:
Based on Persijn answer, you will as well have to change the color of the background to that of its parent.
The whole component would be the figure element, sadly the symbol in the spritesheet will only be used to provide the path and background.
Note: jQuery removed in this version.
jsFiddle
for (var i = 0; i < 100; i++) {
setTimeout(function() {
var progressCounter = document.querySelector(".progress__counter"),
number = document.createElement("span");
progressCounter.appendChild(number);
}, i * 20);
}
#spritesheet {
display: none;
}
.icon {
display: inline-block;
width: 1em;
height: 1em;
}
.icon-bubble {
font-size: 7em;
color: white;
}
.progress-container {
margin: 0;
display: inline-block;
position: relative;
counter-reset: progress;
overflow: hidden;
line-height: 0;
}
.progress__inner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.progress__fill {
background-color: purple;
height: 100%;
transform: translateY(100%);
animation: progressFill 2s steps(100, end) forwards;
}
#keyframes progressFill {
to {
transform: translateY(0);
}
}
.progress__counter {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-40%, -50%);
margin: 0;
font-weight: bold;
}
.progress__counter span {
counter-increment: progress;
}
.progress__counter::after {
content: counter(progress)"%";
}
<figure class="progress-container">
<svg class="icon icon-bubble">
<use xlink:href="#icon-bubble"></use>
</svg>
<figcaption class="progress__inner">
<div class="progress__fill"></div>
<p class="progress__counter"></p>
</figcaption>
</figure>
<svg id="spritesheet">
<symbol id="icon-bubble" viewBox="0 0 79.36 93.844">
<title>Loading Bubble</title>
<path id="bubble-cover" fill="currentColor" stroke="#000" d="M-10,-10 100,-10 100,100 -10,100 -10,-10 50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</symbol>
</svg>
TESTS:
Chrome 53
IE10
Edge
FireFox 47
IOS 10 Safari
PLAYGROUND
jsFiddle
for (var i = 0; i < 100; i++) {
setTimeout(function() {
var progressCounter = document.querySelector(".progress__counter"),
number = document.createElement("span");
progressCounter.appendChild(number);
}, i * 20);
}
#spritesheet {
display: none;
}
.icon {
display: inline-block;
width: 1em;
height: 1em;
}
.icon-bubble {
font-size: 7em;
color: white;
}
.progress-container {
margin: 0;
display: inline-block;
position: relative;
counter-reset: progress;
overflow: hidden;
line-height: 0;
}
.progress__inner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.progress__fill {
background-color: purple;
height: 100%;
transform: translateY(100%);
animation: progressFill 2s steps(100, end) forwards, progressFillColor 100ms linear 2s forwards;
position: relative;
}
#keyframes progressFill {
to {
transform: translateY(0);
}
}
#keyframes progressFillColor {
to {
background-color: green;
}
}
.progress__counter {
position: absolute;
top: 40%;
transform: translateY(-40%);
text-align: center;
width: 100%;
margin: 0;
font-weight: bold;
animation: progressCounter 100ms linear 1s forwards;
}
.progress__counter span {
counter-increment: progress;
}
.progress__counter::after {
content: counter(progress)"%";
animation: progressCounterCompleted 1s linear 2s forwards;
}
#keyframes progressCounter {
to {
color: white;
}
}
/* Chrome Only*/
#keyframes progressCounterCompleted {
33% {
content: "File(s)";
}
66% {
content: "Uploaded";
}
100% {
content: "Successfully!";
}
}
<figure class="progress-container">
<svg class="icon icon-bubble">
<use xlink:href="#icon-bubble"></use>
</svg>
<figcaption class="progress__inner">
<div class="progress__fill"></div>
<p class="progress__counter"></p>
</figcaption>
</figure>
<svg id="spritesheet">
<symbol id="icon-bubble" viewBox="0 0 79.36 93.844">
<title>Loading Bubble</title>
<path id="bubble-cover" fill="currentColor" stroke="#000" d="M-10,-10 100,-10 100,100 -10,100 -10,-10 50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</symbol>
</svg>
SVG with pattern and y transition:
svg:hover pattern #fillshape {
y: 0%;
}
pattern #fillshape {
transition: y 1s;
y: 100%;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
<pattern id="pattern1"
x="0" y="0" width="79.36" height="93.844"
patternUnits="userSpaceOnUse" >
<rect id="fillshape" x="0" y="0" width="100%" height="200%" stroke="none" fill="purple" />
</pattern>
<path fill="url(#pattern1)" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</svg>
Now this does not work in Firefox or Edge. It does not recognize x and y as CSS properties...
Here is a solution that uses a div behind the svg shape.
The downside of this solution is that the svg shape gets a background eg. if you want the shape only you would have to match the background color of the shape with that of the background of the page.
svg {
position: relative;
}
.spesial {
width: 90px;
height: 0px;
display: inline-block;
background-color: purple;
margin-left: -100px;
transition: height 1s;
}
svg:hover + .spesial {
height: 100px;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100" height="100" viewBox="0 0 75 90">
<path stroke="black" fill="gray" d="M-10,-10 100,-10 100,100 -10,100 -10,-10 50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</svg>
<div class="spesial">
</div>
First off, you want to use clip-path, or set the mask fill to white for 100% opacity: mask is used as a greyscale alpha channel and the red fill color causes the opacity change.
As for the stroke, you want to add it as a separate element that is not affected by the clipping. (You can probably re-use the path with defs and use, I just copy-pasted it here)
#progressMove {
transition: .3s y;
}
#progressMove:hover {
y: 60%;
}
<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
<defs>
<clipPath id="bubbleKenseo">
<path d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</clipPath>
</defs>
<path stroke="black" stroke-width="1" fill="transparent" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
<g x="0" y="0" width="79.36px" height="93.844px" clip-path="url(#bubbleKenseo)" height="100">
<rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" />
</g>
</svg>
var prObject = document.getElementById("prObject"),
prDom = document.getElementById("progressMove"),
prValue = 0;
prObject.onmouseenter = function() {
prDom.setAttribute('class', 'prHover')
};
prObject.onmouseleave = function() {
prDom.removeAttribute('class')
};
/*prDom.setAttributeNS(null, 'y', '0');*/
var cTimer = setInterval(function() {
prValue += 20.6;
prDom.style.transform = "translateY(" + [100 - Math.min(prValue, 100)] + "%)";
if (prValue >= 100) {
clearInterval(cTimer);
}
}, 450);
#progressMove {
transition: transform 0.20s linear;
}
#progressMove.prHover {
transform: translateY(40%) !important;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
<defs>
<path id="mypath" fill="white" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
<mask id="bubbleKenseo">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#mypath"></use>
</mask>
</defs>
<g x="0" y="0" width="79.36px" height="93.844px" mask="url(#bubbleKenseo)" height="100" stroke-width="0">
<rect id="progressMove" x="0" y="0" width="100%" height="100%" fill="blue" stroke="black" style="transform: translateY(100%);" />
</g>
<g id="prObject" x="0" y="0" width="79.36px" height="93.844px" height="100" fill-opacity="0" stroke="black" stroke-width="0.5px">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#mypath"></use>
</g>
</svg>
</body>
</html>