9: Transition animation from front to back face
Now that the shake has been set and the back face images and text have been added, the next step is to transition from the shake animation to the transition animation that will rotate the magic 8 ball from the front face to the back face.
For animations to not conflict, one needs to stop before the other one can start if targeting the same element. So for timing, I needed to set the shake to end and then immediately go to the rotation animation to not break the immersion.
Creating the rotation animations
First things first, we need to create the rotation animation, and then we can transition between the shake to the rotation.
I separated the white ball animation and the dark ball animation to simplify the process.
First, for the white ball rotation animation, I set the white ball to move from the centre vertically downwards to give the illusion that the ball was starting to rotate downwards and towards the user.
@keyframes rotateWhite {
0% { top: 50%; left: 50%; transform: translate(-50%, -50%);}
100% {top: 120%; left: 50%; transform: translateX(-50%);}
}
After playing around with the timing, I decided on a 0.8 second timing.
.rotateWhiteBall {
animation: rotateWhite 0.8s;
animation-iteration-count: 1;
}
Next was to set the result ball rotation animation.
I set the dark result circle to again move vertically downwards, but instead from a hidden view above the magic 8 ball to the centre, to again add to the effect of the ball rotating.
@keyframes rotateDark {
0% { top: -50%; left: 50%; transform: translate(-50%, -50%);}
100% {top: 50%; left: 50%; transform: translate(-50%, -50%);}
}
To add to the effect, I kept the timing of both rotations the same at 0.8 seconds.
.rotateDarkBall {
animation: rotateDark 0.8s;
animation-iteration-count: 1;
}
Once the dark result circle reached the centre as the rotation animation finished, I also needed to make sure that the dark circle would not disappear and the white ball would be hidden as the iteration count for both of these was set to 1 and did not specify what to do afterwards.
Implementing the functions
I then set multiple functions (see below) to do the following:
- Reset the white ball to the centre (if it was currently not due to any mouse movements) for the shake animation.
- Add the shake animation to the 'magic 8 ball base', to the 'shine of the ball' and to the 'white ball'.
- I set a timeout function so that after 1.5 seconds, the shake animation class would be removed from these so that it would not conflict with the next animation.
- Then, only for the white circle, I added the white ball rotation animation.
- Again, I set a timeout function so that after 0.8 seconds, the white rotation animation class would be removed, and the white ball would be set to display: none so it would not reappear. In this same timeout function, I then added the dark circle rotation animation to start.
- After 0.8 seconds once the dark circle had reached the centre of the ball base, I then removed the rotation animation class and then set the css of the ball to centre as well as setting the visibility to display: block so that it would stay visible and centered for the results to appear.
- Finally at the very end, I set the 'first shake complete' variable to true, so that now, all future shakes will use the second shake animation rather than the first.
$('#image8BallWhiteCircle').css('top', '50%');
$('#image8BallWhiteCircle').css('left', '50%');
$('#image8BallWhiteCircle').css('transform', 'translate(-50%, -50%)');
$('#image8BallDarkBase, #image8BallShine, #image8BallWhiteCircle').addClass('shakeBall');
setTimeout(function(){
$('#image8BallDarkBase, #image8BallShine, #image8BallWhiteCircle').removeClass('shakeBall');
$('#image8BallWhiteCircle').addClass('rotateWhiteBall');
setTimeout(function(){
$('#image8BallDarkInnerCircle').removeClass('d-none');
$('#image8BallWhiteCircle').addClass('d-none');
$('#image8BallDarkInnerCircle').addClass('rotateDarkBall');
setTimeout(function(){
$('#image8BallDarkInnerCircle').css('top', '50%');
$('#image8BallDarkInnerCircle').css('left', '50%');
$('#image8BallDarkInnerCircle').css('transform', 'translate(-50%, -50%)');
$('#image8BallDarkInnerCircle').removeClass('rotateDarkBall');
}, 800);
}, 800);
}, 1500);
firstShakeCompleted = true;
This then resulted in the below:
