I am trying to animate a 3d card using the javascript animation API. I want the card to move up and either rotate to the left or right slightly. I managed to get it working in Chrome but in Firefox one of the animations glitches out and seems to reset to the centre at the beginning of the animation.
Here is a codepen I created of the issue: https://codepen.io/andy013/pen/MWxmdQp
I can fix this small example by removing the commitStyles() call and not applying any transform styles to the element (although it still seems to glitch out the first time the animation plays). In my real application I can’t do this since I am not applying any styles, but the bug is still present.
I think Firefox is somehow inferring a different starting keyframe. I tried giving a starting keyframe for each animation but that won’t work for my use case as I need to be able to dynamically interrupt the animation at any point and play the reverse animation. I also tried commitStyles() once the animation is interrupted but that didn’t work either.
I am trying to figure out exactly why this issue is happening so I can avoid it in future. It’s strange that the left rotation animation is working fine. If anyone can help point me in the right direction I would be grateful.
Thank you.
Code:
HTML
<div class="card">
<div class="front">
<br><br>
front
</div>
<div class="back">
back
</div>
</div>
</div>
<button onclick="moveup()">Animate up right</button>
<button onclick="reverse()">Animate down right</button>
<button onclick="moveup_left()">Animate up left</button>
<button onclick="reverse_left()">Animate down left</button>
<p>Up right and down right are glitching in firefox</p>
CSS
.card-container {
border: 1px solid red;
width: 95px;
height: 140px;
position: absolute;
top: 80px;
left: 50px;
align-items: center;
justify-content: center;
display: flex;
cursor: pointer;
user-select: none;
}
.card {
border: 1px solid blue;
position: relative;
width: 70px;
height: 96px;
transform-style: preserve-3d;
top: 10px;
left: 10px;
transition: 1s all;
//transform: rotateY(180deg);
backface-visibility: hidden;
}
.back {
position: absolute;
width: 70px;
height: 96px;
backface-visibility: hidden;
background-color: green;
}
.front {
position: absolute;
width: 70px;
height: 96px;
backface-visibility: hidden;
background-color: red;
transform: rotateY(180deg);
}
JS
const anim = document.getElementsByClassName("card")[0].animate(
[
{
transform: `rotateY(180deg) rotateZ(-6deg)`
}
],
{
duration: 0,
fill: `forwards`,
easing: `ease`
}
);
anim.finished.then(() => {
anim.commitStyles();
});
function moveup() {
document.getElementsByClassName("card")[0].animate(
[
{
transform: `translateX(-5px) translateY(-20px) rotateY(180deg) rotateZ(-6deg)`
}
],
{
duration: 400,
fill: `forwards`,
easing: `ease`
}
);
}
function moveup_left() {
document.getElementsByClassName("card")[0].animate(
[
{
transform: `translateX(-5px) translateY(-20px) rotateY(180deg) rotateZ(6deg)`
}
],
{
duration: 400,
fill: `forwards`,
easing: `ease`
}
);
}
function reverse() {
document.getElementsByClassName("card")[0].animate(
[
{
transform: `translateX(0px) translateY(0px) rotateY(180deg) rotateZ(-6deg)`
}
],
{
duration: 400,
fill: `forwards`,
easing: `ease`
}
);
}
function reverse_left() {
document.getElementsByClassName("card")[0].animate(
[
{
transform: `translateX(0px) translateY(0px) rotateY(180deg) rotateZ(6deg)`
}
],
{
duration: 400,
fill: `forwards`,
easing: `ease`
}
);
}