icecub
icecub

Reputation: 8773

CSS rolling ball animation position

General info
I'm working on a Bingo game. Currently I'm trying to create a CSS rolling ball animation. The idea is to simulate a ball dropping from the wheel and making it roll from right to left.

The problem
The animation is working fine. But the "drop in" position is relative to the div. As a consequence of this, this position keeps moving right 75 pixels on each new ball dropping in.

Solutions I've tried
- Give the balls an absolute position. This solves the issue, but each ball will cover the previous balls due to the keyframe ending at left: 0%. This is not desirable.
- Lookup Javascript solutions to see if I can somehow change the keyframe to end with +75px on the previous ball. Unfortunately it seems impossible to manipulate animations this way, or I was unable to find a way to do it.

So now I'm hoping someone is able to help me find a solution to this problem.

Edit: I didn't tag jQuery because it's not used here, but solutions using jQuery are perfectly fine.

MCVE

const timer = setInterval(rollBall, 2000);
var ballNumber = 1;

function rollBall(){
	if(document.getElementById('ball-'+(ballNumber-1))){
  	document.getElementById('ball-'+(ballNumber-1)).classList.remove('ball-animation');
  }
	let html = '<div id="ball-'+ballNumber+'" class="ball ball-animation">';
  html += '<p class="ball-number">';
  html += ballNumber;
  html += '</p></div>';
  
  document.getElementById('balls').innerHTML += html;
  
  ballNumber++;
  
  if(ballNumber > 10) {
  	clearInterval(timer);
    document.getElementById('ball-'+(ballNumber-1)).classList.remove('ball-animation');
  }
}
.ball {
	display: block;
	position: relative;
	width: 75px;
	height: 75px;
	background: red;
	border-radius: 50%;
  background: -webkit-radial-gradient(25px 25px, circle, red, #000);
	background: -moz-radial-gradient(25px 25px, circle, red, #000);
	background: radial-gradient(25px 25px, circle, red, #000);
	/*position: absolute;*/
	float: left;
}

.ball-number {
	top: -34px;
	left: 25px;
	font-size: 45px;
	color: #fff;
	position: absolute;
}

.ball-animation {
	-webkit-animation: spin 1750ms linear infinite, moveRightToLeft 2s linear infinite;
	-moz-animation: spin 1750ms linear infinite, moveRightToLeft 2s linear infinite;
	-ms-animation: spin 1750ms linear infinite, moveRightToLeft 2s linear infinite;
	animation: spin 1750ms linear infinite, moveRightToLeft 2s linear;

	-webkit-transition: all 1.75s ease;
	transition: all 1.75s ease;
}

@keyframes spin {
	from { transform: rotate(360deg); }
	to { transform: rotate(0deg); }
}

@keyframes moveRightToLeft {
	0% { top: -50px; left: 200px; }
	10% { top: -40px; left: 180px; }
	20% { top: -25px; left: 150px; }
	30% { top: 0px; left: 100px; }
	100% { left: 0%; }
}
<div id="balls"></div>

Upvotes: 3

Views: 2696

Answers (1)

vals
vals

Reputation: 64164

This is a CSS only solution, using an intermediate div, zone to handle the ball movement .

Since this elements have varying sizes, you can set the keyframes on them to work in percentages, and adjust for a different ending point, while keeping the same origin point.

.container {
    width: 600px;
    height: 350px;
    border: solid 1px red;
    position: relative;
}

.zone {
    position: absolute;
    top: 0px;
    right: 0px;
    bottom: 40px;
    left: 40px;
    border: solid 1px green;
    animation: move 3s linear infinite;
}

.zone:nth-child(2) {
    left: calc(40px * 2);
}

.zone:nth-child(3) {
    left: calc(40px * 3);
}
.zone:nth-child(4) {
    left: calc(40px * 4);
}

.ball {
    width: 40px;
    height: 40px;
    border-radius: 100%;
    background-color: blue;
    right: 0px;
    position: absolute;
}

@keyframes move {
    from {transform: translate(0px, 0px);}
    50% {transform: translate(-100px, 100%);}
    to {transform: translate(-100%, 100%);}
}
<div class="container">
  <div class="zone">
    <div class="ball">1</div>
  </div>
  <div class="zone">
    <div class="ball">2</div>
  </div>
  <div class="zone">
    <div class="ball">3</div>
  </div>
  <div class="zone">
    <div class="ball">4</div>
  </div>
</div>

Upvotes: 2

Related Questions