I am animating a svg element currently like following
.r1 {
transform-box: fill-box;
transform-origin: 50% 50%;
animation-name: simpleRotation,xRotation;
animation-delay: 0s, 2s;
animation-duration: 2s;
animation-iteration-count: 1, 1;
animation-timing-function: linear;
animation-direction: normal;
animation-fill-mode: forwards;
}
@keyframes simpleRotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
@keyframes xRotation {
from {
transform: rotateX(0deg);
}
to {
transform: rotateX(359deg);
}
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect id="r1" x="10" y="10" width="10" height="10" stroke="black" stroke-width="0.25" fill="orange"></rect>
</svg>
Is it possible to queue the animations (with javascript) in a way so that every 2s the animation runs one after another in a loop such as simpleRotation(0-2s);xRotation(2-4s);simpleRotation(4-6s);xRotation(6-8s);simpleRotation(8-10s);.....
CodePudding user response:
An alternative might be using the Web Animations API
The keyframe animation can be translated to an animation object like this
let ani1 = animEl.animate(
[{
transform: "rotate(0deg)"
}, {
transform: "rotate(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1
}
);
See also: MDN: Using the Web Animations API
Example
let animEl = document.querySelector(".rect1");
let ani1 = animEl.animate(
[{
transform: "rotate(0deg)"
}, {
transform: "rotate(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1
}
);
let ani2 = animEl.animate(
[{
transform: "rotateX(0deg)"
}, {
transform: "rotateX(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1,
}
);
// pause 2. animation
ani2.pause();
// chain animations
ani1.onfinish = function() {
ani2.play();
};
ani2.onfinish = function() {
ani1.play();
};
svg {
border: 1px solid #ccc;
display: block;
width: 10em
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect id="r1" x="25" y="25" width="50" height="50" stroke="black" stroke-width="0.25" fill="orange" transform-origin="50 50" ></rect>
</svg>
We pause the second on start animation via
ani2.pause();
and add an eventListener to start the first animation after the first one has finished.
ani1.onfinish = function() {
ani2.play();
};
CodePudding user response:
This is a case where the SVG animation format is easier to use than the CSS keyframe animation - in principle.
SVG animations can define the begin time of an animation in relation to events - among them the end of another animation. This way you can chain animations together, and you can define loops:
<animate id="first" begin="0s;second.end" ... />
<animate id="second" begin="first.end" ... />
The first animation begins at 0s
and additionally is triggered by the end of the second animation, and the second animation is triggered by the end of the first animation.
The problem with your use case is that you want to animate 3D transform functions. SVG transform
differs in syntax from CSS transform
, and does only support 2D transformations. So the following example at best can simulate the effect, and a number of details has to be written in a different manner.
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect id="r1" x="-5" y="-5" transform="translate(15 15)"
width="10" height="10" stroke="black" stroke-width="0.25" fill="orange">
<animateTransform id="simpleRotation" attributeName="transform" type="rotate"
additive="sum" begin="0s;xRotation.end" dur="2s"
from="0" to="360" />
<animateTransform id="xRotation" attributeName="transform" type="scale"
additive="sum" begin="simpleRotation.end" dur="2s"
values="1 1;1 -1;1 1" keyTimes="0;0.5;1"
calcMode="spline" keySplines=".375 0 .375 1;.375 0 .375 1" />
</rect>
</svg>
- the center of the animated object is initially placed at
0,0
to simplify the following transforms. Each<animateTransform>
gets aadditive="sum"
attribute so that it is post-multiplied to the statictranslate()
attribute on the animated object. - to simulate
xRotate()
, ascale
transform is used that scales the y axis from 1 to -1 and back. Additionally, a spline interpolation is defined to give the impression of a smooth "rotation". Note that this simulation only works in absence of aperspective
.