Looping parallax effect on full-width element keeps jumping in CSS / JS - javascript

My preferred end goal is to have a performance friendly background that smoothly loops without jumping. All the resources that I have found online either are not very performance friendly or they only work with elements that have a set width.
Currently everything looks okay, but the background scales poorly on different screens, and will make large jumps occasionally. I assume the jumping is due to an error in the translation of the elements, but I haven't yet seen a good solution. Setting the width of the elements to 200% and translating them over -50% seems like a hacky solution, and I feel as if there should be a much better way of doing it.
I would prefer to find an all CSS solution, but if nothing else is feasible, resorting to JS is fine.
Fiddle: https://jsfiddle.net/r4fz0Lot/3/
Code:
* { box-sizing: border-box; }
html, body, #container { width: 100%; height: 100%; }
body { margin: 0; }
#container {
background-color: rgba(0, 0, 0, 0.9);
image-rendering: pixelated;
overflow: hidden;
position: fixed;
}
#stars {
background: url('https://i.imgur.com/Ym03Zkf.png') repeat 0 0;
animation: loop 25s linear infinite;
z-index: 1;
}
#mountains {
background: url('https://i.imgur.com/jfef1r3.png') repeat-x 0 bottom;
animation: loop 20s linear infinite;
z-index: 2;
}
#ground {
background: url('https://i.imgur.com/P13CzUo.png') repeat-x 0 bottom;
animation: loop 15s linear infinite;
z-index: 3;
}
#stars, #mountains, #ground {
width: 200%; height: 100%;
background-size: 30%;
bottom: 0; left: 0;
position: fixed;
}
#keyframes loop {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
<div id="container">
<div id="ground"></div>
<div id="mountains"></div>
<div id="stars"></div>
</div>

You set background-size to 30% so you need to translate some multiple of 30% to translate "one image unit"
* { box-sizing: border-box; }
html, body, #container { width: 100%; height: 100%; }
body { margin: 0; }
#container {
background-color: rgba(0, 0, 0, 0.9);
image-rendering: pixelated;
overflow: hidden;
position: fixed;
}
#stars {
background: url('https://i.imgur.com/Ym03Zkf.png') repeat 0 0;
animation: loop 8s linear infinite;
z-index: 1;
}
#mountains {
background: url('https://i.imgur.com/jfef1r3.png') repeat-x 0 bottom;
animation: loop 6s linear infinite;
z-index: 2;
}
#ground {
background: url('https://i.imgur.com/P13CzUo.png') repeat-x 0 bottom;
animation: loop 5s linear infinite;
z-index: 3;
}
#stars, #mountains, #ground {
width: 200%; height: 100%;
background-size: 30%;
bottom: 0; left: 0;
position: fixed;
}
#keyframes loop {
from { transform: translateX(0); }
to { transform: translateX(-30%); }
}
<div id="container">
<div id="ground"></div>
<div id="mountains"></div>
<div id="stars"></div>
</div>

Related

Endless road animation CSS3

I have this 2D Highway background image
https://opengameart.org/sites/default/files/background-1_0.png
I'm working on a mobile game (with JS and CSS3) of racing cars,
and I want to make animation of this road to make an illusion of movement
Can someone please guide me what's the best practice for this case?
Currently I do something like that, but it's not smooth enough (especially in mobile browser) -
.main {
background-image: url(https://opengameart.org/sites/default/files/background-1_0.png);
background-repeat-x: no-repeat;
background-size: 103%;
background-repeat-y: repeat;
background-position-y: 27px;
animation: loopingRoad 0.1s infinite;
height: 100%;
width: 100%;
}
#keyframes loopingRoad {
100% {
background-position-y: 1000%;
}
0% {
background-position-y: 0%
}
}
Use
background-position: 0 0;
background-position: 0 -100000px;
as the keyFrame keys:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
.main {
background-image: url(https://opengameart.org/sites/default/files/background-1_0.png);
background-repeat-x: no-repeat;
background-size: 103%;
background-repeat-y: repeat;
background-position-y: 27px;
animation: loopingRoad 250s linear infinite;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
#keyframes loopingRoad {
from {
background-position: 0 0;
}
to {
background-position: 0 -100000px;
}
}
<div class="main" />
Create a container in which you set the aspect ratio that corresponds with the road image. This allows you to play with the width of the container while keeping the image in the right proportions.
For the image itself. Make it twice the height of the container. This allows you to transform the entire road 50% upwards. When starting the animation, the top half of the road is exposed. At the end of the animation the bottom half is exposed. Loop this proces to create the illusion.
The transform property animates very well as it doesn't ask the browser to repaint the entire page, but only the element that is transformed.
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
.view {
max-width: 840px;
max-height: 100%;
overflow: hidden;
}
.road {
aspect-ratio: 840 / 650; /* Dimensions of the road image */
overflow: hidden;
}
.road::before {
content: "";
display: block;
animation: loopRoad 1.5s infinite linear;
height: 200%; /* Twice the height */
background-size: auto 50%; /* Fit into 1 vertical half */
background-image: url(https://opengameart.org/sites/default/files/background-1_0.png);
background-repeat: repeat-y;
}
#keyframes loopRoad {
from {
transform: translate3d(0, 0%, 0);
}
to {
transform: translate3d(0, -50%, 0);
}
}
<div class="view">
<div class="road"></div>
</div>

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>
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>

Trying to make a CSS3 diagonal slide animation, but it's not working as expected

So I'm trying to create a diagonal scroll in CSS3, but I'm having no luck.
The original script is this: https://codepen.io/275845/pen/LoYBjg
<style>
.tech-slideshow {
height: 600px;
max-width: 800px;
margin: 0 auto;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
}
.tech-slideshow > div {
height: 100px;
width: 2526px;
background: url(https://i2.wp.com/mitmark.com.br/wp-content/uploads/2016/04/circle.png?ssl=1);
position: absolute;
top: 0;
left: 0;
height: 100%;
transform: translate3d(0, 0, 0);
}
.tech-slideshow .mover-1 {
animation: moveSlideshow 12s linear infinite;
}
.tech-slideshow .mover-2 {
opacity: 0;
transition: opacity 0.5s ease-out;
background-position: 0 -200px;
animation: moveSlideshow 15s linear infinite;
}
#keyframes moveSlideshow {
100% {
transform: translateX(-66.6666%);
}
}
</style>
<div class="tech-slideshow">
<div class="mover-1"></div>
<div class="mover-2"></div>
</div>
Here's what I've tried so far, with no success: https://codepen.io/275845/pen/gJOjXY
<style>
.tech-slideshow {
height: 600px;
max-width: 800px;
margin: 0 auto;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
}
.tech-slideshow > div {
height: 100px;
width: 2526px;
background: url(https://i2.wp.com/mitmark.com.br/wp-content/uploads/2016/04/circle.png?ssl=1);
position: absolute;
top: 0;
left: 0;
height: 100%;
transform: translate3d(0, 0, 0);
}
.tech-slideshow .mover-1 {
animation: moveSlideshow 2s linear infinite;
}
.tech-slideshow .mover-2 {
opacity: 0;
transition: opacity 0.5s ease-out;
background-position: 0 -200px;
animation: moveSlideshow 5s linear infinite;
}
#keyframes moveSlideshow {
0% {
transform: translatex(0px) translatey(0px)
}
100% {
transform: translatex(100px) translatey(100px);
}
}
</style>
And here's the result that I'm trying to achieve: https://streamable.com/ltsba
As you can see, I'm trying to make a diagonal slide scrolling in css3, but of course, if anyone could point me out another solution weather it's vanilla javascript, or even jQuery, I'm opened for new suggestions.
You're pretty close, just a few issues.
You don't need 2 "mover", one is enough.
Make it big! And background repeat!
Then you move the size of that background image.
.tech-slideshow > div {
height: 3000px; // BIG
width: 3000px;
background: url(https://i2.wp.com/mitmark.com.br/wp-content/uploads/2016/04/circle.png?ssl=1);
position: absolute;
bottom: 0;. // position
right: 0;
animation: moveSlideshow 5s linear infinite;
}
#keyframes moveSlideshow {
0% {
transform: translatex(0px) translatey(0px);
}
100% {
transform: translatex(255px) translatey(255px); // move size of image
}
}

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.

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!

Categories

Resources