To aid my newbie journey into JS I'm trying to make a simple game - where there are pieces of 'rubbish' (divs) floating from right to left down a river, then when a player clicks the div it disappears.
I'm stuck trying to add randomness to the animation, so each piece of rubbish will take a different path.
I was hoping there would be a way to pass a random value into the 'top' percentages of the keyframe animation, something like this - any ideas how it could be adapted? I wouldn't mind all the animation being placed into JS
const btnRubbish = document.querySelector('div.smallrubbish')
const x = (Math.random() * 100)
btnRubbish.style.transform =
`@keyframes rubbish {
0% {top: ${x}%; left: 100%;}
50% {top: ${x}%; left: 50%;}
100% {top: ${x}%; left: 0%;}`
HTML
<div class="game box">
<div class="smallrubbish"></div>
</div>
Relevant CSS
div.smallrubbish {
display: block;
height: 50px;
width: 50px;
background-color: rgba(255, 124, 0, 1);
border-radius: 100%;
position: absolute;
top: 50%;
left: 100%;
animation-name: rubbishflow;
animation-duration: 8s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-delay: 0s;
animation-fill-mode: forwards;
}
@keyframes rubbishflow {
0% {top: 50%; left: 100%;}
50% {top: 25%; left: 50%;}
100% {top: 60%; left: 0%;}
}
The basic question is how to randomly create keyframes for CSS animations and have them loaded at runtime.
The @keyframes definitions cannot be added inline to an element. But you can change the animation name of an element by
el.style.animationName = 'animation'
and you can add style elements to your documents head at runtime. Taking the simple example given in the question here's a snippet to add random y values to an animation and give a piece of rubbish that animation:
const head = document.getElementsByTagName('head')[0];
const btnRubbish = document.querySelector('div.smallrubbish');
let keyframes =
`@keyframes rubbish {
0% {top:` + (Math.random() * 100) + `%; left: 100%;}
50% {top:` + (Math.random() * 100) + `%; left: 50%;}
100% {top:` + (Math.random() * 100) + `%; left: 0%;}`;
let style= document.createElement('STYLE');
style.innerHTML = keyframes;
head.appendChild(style);
btnRubbish.style.animationName = 'rubbish';
div.smallrubbish {
display: block;
height: 50px;
width: 50px;
background-color: rgba(255, 124, 0, 1);
border-radius: 100%;
position: absolute;
top: 50%;
left: 100%;
animation-name: rubbishflow;
animation-duration: 8s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-delay: 0s;
animation-fill-mode: forwards;
}
<div class="game box">
<div class="smallrubbish"></div>
</div>
It will be possible to say create a random number of frames in the animation, with random % values and with random x-axis positions (always ensuring going from right to left - unless your rubbish can get caught in an eddy of course). And each piece of rubbish could have a different animation-duration
.
There is the question of how to keep track of the styles added and how to allocate new ones to each piece of rubbish. The logistics of this depend on how complex the game situation is to become - for example is the game to go on forever - in which case you could end up running out of space so keeping a record of pieces of rubbish and of keyframes will be needed so you can either reuse them or get rid of them when no longer needed.