CSS rolling ball animation position - javascript

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>

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>

Related

Is there a way to make an element spin around without a variable telling how far it has already turned?

I have an experimental website that plays music, and I want the forward and backward buttons to spin when you click them. But, I also don't want to have 2 variables to be how far they have turned, or a function to get how far they have turned from the CSS transform property. They have a transition, for hover effects. I have tried
backward.classList.add("notrans");
backward.style.transform = "rotateZ(0deg)";
backward.classList.remove("notrans");
backward.style.transform = "rotateZ(-360deg)";
and some closely related things, and also have a setTimeout to reset it afterwards, which it too long for a post.
Animate is what you are searching for.
This should be a working example: (Tested in FF and Chrome)
/* THIS IS A JAVASCRIPT CLASS THAT ADDS AND
REMOVES THE CSS CLASS FROM YOUR ELEMENT
USING THE ELEMENT'S ID VALUE TO REFERENCE. */
function startStop(strstp) {
var infinite = document.getElementById("imSpinning");
var once = document.getElementById("imSpinningOnce");
if(strstp == 1)
{
infinite.classList.add("spin");
once.classList.add("spinOnce");
timer = setTimeout(function() {
once.classList.remove("spinOnce");
},1000);
}
else
{
infinite.classList.remove("spin");
once.classList.remove("spinOnce");
}
}
/* THIS IS THE CSS CLASS THAT CREATES INFINITE ROTATION */
.spin {
-webkit-animation:spin 1s linear infinite;
-moz-animation:spin 1s linear infinite;
animation:spin 1s linear infinite;
}
#-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
#-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
#keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
/* THIS IS THE CSS CLASS THAT ROTATES ONCE */
.spinOnce {
-webkit-animation:spin 1s linear;
-moz-animation:spin 1s linear;
animation:spin 1s linear;
}
#-moz-keyframes spinOnce { 100% { -moz-transform: rotate(360deg); } }
#-webkit-keyframes spinOnce { 100% { -webkit-transform: rotate(360deg); } }
#keyframes spinOnce { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
<div style="width: 100px; height: 30px; background-color: green; color: white; margin: 20px; text-align: center; cursor: pointer;" onclick="startStop(1)">
GO
</div>
<div style="width: 100px; height: 30px; background-color: red; color: white; margin: 20px; text-align: center; cursor: pointer;" onclick="startStop(0)">
STOP
</div>
<!-- ELEMENT TO ROTATE INFINITLY WITH "spin" CLASS -->
<div id="imSpinning" class="spin" style="position: absolute; top: 10px; right: 30px; height: 140px; width: 140px; background-image: url(https://icons.iconarchive.com/icons/thehoth/seo/256/seo-web-code-icon.png); background-size: 100% 100%; background-position: center center; border-radius: 50%; overflow: hidden;"></div>
<!-- ELEMENT TO ROTATE ONCE WITH "spin" CLASS -->
<div id="imSpinningOnce" class="spinOnce" style="position: absolute; top: 10px; right: 200px; height: 140px; width: 140px; background-image: url(https://icons.iconarchive.com/icons/thehoth/seo/256/seo-web-code-icon.png); background-size: 100% 100%; background-position: center center; border-radius: 50%; overflow: hidden;"></div>
Simply copy the CSS class above to the style section/sheet of your page and modify it as needed. Ensure you reference the class in your html element.
Also I edited in a small JavaScript class that add/removes the spin class from the DIV element if it helps you in starting and stopping the animation.
Hope this helps, and best of luck!

Js/jQuery - This code sets a size to a variable, any way to make it responsive?

A non-programmer here, looking for help. :)
I've been searching for a way to make two circles spin inside a larger circle, in a very particular fashion, and I found some code which I managed to tweak to get exactly the effect I wanted:
However, the full width of it is 400px (I need it to be so), and the problem is that the code defines the radius and positioning values in absolute, so if the browser goes below 400px width, it can't be adjusted:
var r = 101;
var xcenter = 100;
var ycenter = 100;
var newLeft = Math.floor(xcenter + (r * Math.cos(t)));
var newTop = Math.floor(ycenter + (r * Math.sin(t)));
Now, I would be content if I could simply scale this whole thing for browsers < 400px down to
var r = 71;
var xcenter = 70;
var ycenter = 70;
var newLeft = Math.floor(xcenter + (r * Math.cos(t)));
var newTop = Math.floor(ycenter + (r * Math.sin(t)));
But I haven't the slightest clue how to go about implementing that responsiveness, or even if it's possible to do in real time (without having to refresh the browser, cos I'd like it to be resize-proof).
Here is the full fiddle of what I have: http://jsfiddle.net/29or8u76/3/
So... can someone help me out? Cos I don't really speak javascript at all :) Thanksss!
This does not directly answer your question, but here's an example using only CSS.
I've used percentages to keep everything responsive to the container width.
The inner circles rotate around their origins by using animation, which uses transform.
The pulsing of the outer circle is just for demonstration purposes, to show how the size of the inner circles are relative to their container.
#container {
position: relative;
height: 0;
border: 1px solid #000;
border-radius: 50%;
margin: 0 auto;
animation: pulse 5s 0s linear infinite;
}
.circle {
position: absolute;
width: 50%;
height: 50%;
border-radius: 50%;
animation: spin 3s 0s linear infinite;
}
#blue {
top: 0;
left: 25%;
transform-origin: center bottom;
background-color: #00f;
}
#red {
bottom: 0;
left: 25%;
transform-origin: center top;
background-color: #f00;
}
#keyframes spin {
100% {
transform: rotate(360deg);
}
}
#keyframes pulse {
0% {
width: 25%;
padding-bottom: 25%;
}
50% {
width: 10%;
padding-bottom: 10%;
}
100% {
width: 25%;
padding-bottom: 25%;
}
}
<div id="container">
<div class="circle" id="blue"></div>
<div class="circle" id="red"></div>
</div>
EDIT:
To ensure that the contents of the circles don't rotate, I've used a slightly different method that animates the circles in orbit around the container's center.
This method is based on a tutorial by Zoltan Howryluk.
#container {
position: relative;
height: 0;
border: 1px solid #000;
border-radius: 50%;
margin: 0 auto;
animation: pulse 5s 0s linear infinite;
}
.circle {
position: absolute;
width: 50%;
height: 50%;
top: 25%;
left: 25%;
border-radius: 50%;
transform-origin: center;
display: flex;
justify-content: center;
align-items: center;
}
.circle span {
font-size: 10px;
color: white;
}
#blue {
background-color: #00f;
transform: translateY(-50%);
animation: orbit1 3s 0s linear infinite;
}
#red {
background-color: #f00;
transform: translateY(50%);
animation: orbit2 3s 0s linear infinite;
}
#keyframes orbit1 {
from {
transform: rotate(0deg) translateX(50%) rotate(0deg);
}
to {
transform: rotate(360deg) translateX(50%) rotate(-360deg);
}
}
#keyframes orbit2 {
from {
transform: rotate(0deg) translateX(-50%) rotate(0deg);
}
to {
transform: rotate(360deg) translateX(-50%) rotate(-360deg);
}
}
#keyframes pulse {
0% {
width: 25%;
padding-bottom: 25%;
}
50% {
width: 10%;
padding-bottom: 10%;
}
100% {
width: 25%;
padding-bottom: 25%;
}
}
<div id="container">
<div class="circle" id="blue"><span>BLUE</span></div>
<div class="circle" id="red"><span>RED</span></div>
</div>
Before deciding on this method, I recommend considering browser compatibility and vendor prefixes for various CSS3 functionality. For simplicity, I haven't included any vendor prefixes here.

Moving div along the circular path with fixed angle

I would like to know if it is possible to move div along the circular path with fixed angle. E.g. moving div only 45 degrees of circular path and than make it to come back to starting point, like effect similar to pendulum.
Hope, that attached picture will make sense to what I meant.
Many thanks for all help.
Looking forward,
As per your updated requirement (that the object itself should always be vertical while rotating), I have modified my previous code.
There may be another approach but I could think of this only at the moment. Here, I have wrapped our original 'ball' element inside another div. Now, the outer div does the normal pendulum animation. But, in addition, the inner object also does a counter-rotating animation which keeps it vertically straight at all points during the animation.
Please notice that the inner object has its transform-origin as default which is center center, because it needs to rotate around its own axis only.
#container
{
background-color: #777;
border-radius: 50%;
height: 20px;
margin: 0 auto;
margin-top: 150px;
position: relative;
width: 20px;
}
#ball
{
animation: swing 1s ease 0s infinite;
background-color: green;
height: 50px;
left: -15px;
position: absolute;
top: -150px;
transform-origin: center 150px;
width: 50px;
}
#keyframes swing{
0%{transform: rotate(-22.5deg);}
50%{transform: rotate(22.5deg);}
100%{transform: rotate(-22.5deg);}
}
#main-content
{
animation: innerswing 1s ease 0s infinite;
background-color: red;
display: block;
height: 100%;
width: 100%;
}
#keyframes innerswing{
0%{transform: rotate(22.5deg);}
50%{transform: rotate(-22.5deg);}
100%{transform: rotate(22.5deg);}
}
<div id="container">
<div id="ball">
<div id="main-content"></div>
</div>
</div>
You can do this using css animation alone. First you should shift the transform origin to a point that will server as the center of the pendulum. Now, you can simply define the angles for rotation as being 45 degree apart. Please check below code as an example:
#container
{
background-color: #777;
border-radius: 50%;
height: 20px;
margin: 0 auto;
margin-top: 150px;
position: relative;
width: 20px;
}
#ball
{
animation: swing 1s ease 0s infinite;
background-color: orange;
border-radius: 50%;
height: 50px;
left: -15px;
position: absolute;
top: -150px;
transform-origin: center 150px;
width: 50px;
}
#keyframes swing{
0%{transform: rotate(-22.5deg);}
50%{transform: rotate(22.5deg);}
100%{transform: rotate(-22.5deg);}
}
<div id="container">
<div id="ball"></div>
</div>

Create a folding animation of a simple square

I am trying to make this animation. This animation is quite complicated, but all I would like to do is fold a square in half showing the folding animation.
I have visited this website and I tried to use the skew function in order to create the animation.
This is the code I have used so far:
.elementLeft {
display: inline-block;
background-color: #aaaaaa;
height: 100px;
width: 100px;
font-size: 1px;
animation: shakeback 2s infinite;
animation-direction: alternate;
color: white;
}
.elementRight {
display: inline-block;
background-color: #aaaaaa;
height: 100px;
width: 100px;
/* transform: skew(20deg); */
font-size: 1px;
color: white;
animation: shake 2s infinite;
animation-direction: alternate;
}
#keyframes shake {
0% {
transform: skewY(0deg);
}
100% {
transform: skewY(45deg);
}
}
#keyframes shakeback {
0% {
transform: skewY(0deg);
}
100% {
transform: skewY(-45deg);
}
}
body,
html {
height: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
}
<div class="elementLeft"></div>
<div class="elementRight">
</div>
However, this is not exactly what I want since the skew function also makes the square too long as I increase the degree. I have been thinking of another way to create this animation, but I am not sure what to do. I also would prefer that only one side folds in rather than both sides folding. This is like in the Google Calendar Icon animation posted above where the top half of the icon stays still whereas the bottom half folds upwards.
edit: I have also noticed that I can rotate a square upwards to form this effect. However, I am still having an issue as the animation does not look as smooth as I would like.
Any help is once again appreciated!
.element {
display: inline-block;
background-color: #000000;
height: 100px;
width: 100px;
}
.elementfold {
/* transform: rotateX(0deg); */
animation: foldup 5s;
display: inline-block;
background-color: #aaaaaa;
height: 100px;
width: 100px;
}
#keyframes foldup {
0% {
transform: rotateX(0);
}
100% {
transform: rotateX(180deg) translate(0px, 100px);
}
}
<li>
<div class="element"></div>
</li>
<li>
<div class="elementfold"></div>
</li>
This may be useful. I haven't tried it myself, but I'd look into it.
http://anime-js.com/
Code:
#container {
width: 100px;
height: 100px;
perspective: 300px;
}
.square {
width: 100px;
height: 100px;
background-color: grey;
}
#animation {
animation: anim 2s linear 0s infinite alternate;
transform-origin: 50% 100%;
}
#keyframes anim {
from {transform: rotateX(0deg);}
to {transform: rotateX(-180deg);}
}
<div id="container">
<div class="square" id="animation"></div>
<div class="square"></div>
</div>
Using CSS3's rotateX property and animations, it's pretty easy to create folding squares.
Credit goes to Bálint for the animations!
The above method will need to be slightly tweaked the object is rounded. In the case that the folding animation needs to be applied to a circle or an oval, it can be done by breaking the shape into two shapes; more specifically, the circle would be broken into two semicircles.
The following code shows one solution for this using HTML and LESS (for this reason it will not load on stackoverflow):
#size: 200px;
.origin (#x;
#y) {
-webkit-transform-origin: #x #y;
-moz-transform-origin: #x #y;
-o-transform-origin: #x #y;
transform-origin: #x #y;
}
.red {
background-color: #f24235;
}
.green {
background-color: lightgreen;
}
.top-half {
width: #size;
height: (#size / 2);
border-radius: (#size / 2) (#size / 2) 0 0;
}
.bottom-half {
width: #size;
height: (#size / 2);
border-radius: 0 0 (#size / 2) (#size / 2);
.origin(0, 0);
}
#animation {
animation: anim 2s linear 0s infinite alternate;
// transform-origin: 50% 100%;
}
#container {
width: 100px;
height: 100px;
perspective: 300px;
}
#keyframes anim {
from {
transform: rotateX(0deg);
}
to {
transform: rotateX(180deg);
}
}
<div class "container">
<div class="top-half red"></div>
<div class="bottom-half green" id="animation"></div>
</div>
Please follow this link to see the animation. If there are any other efficent ways to do this with a variable size, but through either normal css or js please let me know!

get #keyframe current value in css3 with javascript

See the demo here:
http://jsfiddle.net/hamidrezabstn/fgcPa/5/
When I click on the middle raindrop , I would like it to rotate to the current position of the spinning circle! I tried below the JS code but it doesn't work! The next thing I want to do is the raindrop rotate with spining circle!
$(function() {
$('#center').click(function() {
var pos = $('#circle').css('transform')
$(this).css('transform', 'pos')
});
});
$(function() {
$('#center').click(function() {
var obj, matrix;
obj = document.getElementById('circle');
matrix = getComputedStyle(obj).getPropertyValue('transform');
console.log(matrix);
//$(this).css('transform', matrix)
});
});
read more here http://dev.opera.com/articles/view/understanding-3d-transforms/
EDITED: I said that it is not posible to get the current status of the transform in an animation, but I was wrong. Sorry about that !
To do what you want, any way, you don't need really to get it; just use it.
I have changed slightly your HTML to put the raindrop inside the rotating div.
Then, with this CSS:
.raindrop {
background:center blue;
width:50px;
height:50px;
border-radius: 100%;
border-top-left-radius: 0;
position: absolute;
margin: auto;
left: 75px;
top: 75px;
animation: ccircle 5s infinite linear;
-webkit-animation: ccircle 5s infinite linear;
}
.raindrop:hover {
animation: none;
-webkit-animation: none;
}
.axis {
width: 200px;
height: 200px;
transform: scaleX(2);
background-color: none;
border: 1px solid black;
left: 50px;
position: absolute;
top: 50px;
border-radius: 50%;
}
.rotate {
width: 100%;
height: 100%;
top: 0px;
animation: circle 5s infinite linear;
-webkit-animation: circle 5s infinite linear;
transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
position: absolute;
}
.counterrotate {
width: 50px;
height: 50px;
animation: ccircle 5s infinite linear;
-webkit-animation: ccircle 5s infinite linear;
}
.planet {
width: 50px;
height: 50px;
position: absolute;
border-radius : 50px;
left: 0px;
top: 0px;
background-color: red;
display: block;
}
#keyframes circle {
from { transform: rotateZ(0deg) }
to { transform: rotateZ(360deg) }
}
#-webkit-keyframes circle {
0% { -webkit-transform: rotateZ(0deg) }
100% { -webkit-transform: rotateZ(360deg) }
}
#keyframes ccircle {
from { transform: rotateZ(360deg) }
to { transform: rotateZ(0deg) }
}
#-webkit-keyframes ccircle {
from { -webkit-transform: rotateZ(360deg) }
to { -webkit-transform: rotateZ(0deg) }
}
You got this fiddle
In it, the raindrop is always rotating with the axis div. But it is also counter-rotating, so it appears to be static.
When you hover it, the count-rotation is disabled, and it points to red circle. And will continue to do so as long as you hover it.
To do that thru a click, just asociate the :hover properties to a class, and set this class in the click.

Categories

Resources