2

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%;}
}
3
  • I don't think you can change keyframes like that, you'd have to update/add them to the head of your document. This would be possible, but it might be easier to keep track of things by using transitions instead - as you can put the transition in the style of each rubbish element as you create the element. How are you creating/deleting the rubbish elements. Commented Nov 21, 2020 at 20:46
  • Hey A - thanks for your thoughts! Transitions are a good idea, I wonder if I could randomise the bezier curve values to get difference in the way each element moves? The rubbish is just a div, then I've made a JS function to assign a different image each time the animation plays. You can see a beta version here - still very in progress(!) games-1.superhi.com Commented Nov 22, 2020 at 16:05
  • Don't see why not. I'll have a think tomorrow, but you may have solved it by then. You have given me an idea for tidying up a similar game, Splat Medusa [link]rgspaces.org.uk/games/splat/forbury-lion/splat-medusa, which is now very old and could do with using more modern CSS. Commented Nov 22, 2020 at 18:57

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

It works! Thank you for this! I'd never used the head element to start a function before, that was useful learning for me. I've added images to the game now and managed to randomis them, next step will be figuring out how the div restarts. Thanks again for your help - also I love your splat medusa game! It's so satisfying to explode the heads.
In the code you basically add the keyframes to the style section, so will this work if (a) there are no style tags existing in the head (b) there already exists a style tag.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.