Im trying to layer 2 images 1 on top of the other and make them scroll infinitely using jQuery. I am able to make the images scroll and layer in CSS but the animation becomes very jerky. How could I create an infinite horizontal scroll on an image using jQuery and keep the animations smooth?
My code so far:
CSS:
#keyframes animatedBackground {
from { background-position: 0 0; }
to { background-position: 100% 0; }
}
#animate-area {
width: 100vw;
height: 100vw;
background-image: url(http://oi64.tinypic.com/2r7ri29.jpg);
background-position: 0px 0px;
background-repeat: repeat-x;
animation: animatedBackground 135s linear infinite;
}
#animate-area2 {
width: 100vw;
height: 100vw;
background-image: url(http://oi67.tinypic.com/2niy905.jpg);
background-repeat: repeat-x;
position: relative;
animation: animatedBackground 80s linear infinite;
}
and HTML:
<div id="animate-area"></div>
<div id="animate-area2"></div>
JSFiddle
Check it out. Maybe you will like it.
https://jsfiddle.net/hnxnjzaq/3/
Basically just used translate instead of background-position.
#keyframes animatedBackground {
from { transform: translateX(0); }
to { transform: translateX(100%); }
}
Just adjust the speed as you wish.
Change your
#keyframes animatedBackground {
from { background-position: 0 0; }
to { background-position: 100% 0; }
}
to:
#keyframes animatedBackground {
from { background-position: -100% 0; }
to { background-position: 100% 0; }
}
The snippet:
body {
background-color: black;
}
#keyframes animatedBackground {
from { background-position: -100% 0; }
to { background-position: 100% 0; }
}
#animate-area {
width: 100vw;
height: 100vw;
background-image: url(http://oi64.tinypic.com/2r7ri29.jpg);
background-position: 0px 0px;
background-repeat: repeat-x;
position:absolute;z-index:-2;
animation: animatedBackground 135s linear infinite;
}
#animate-area2 {
width: 100vw;
height: 100vw;
background-image: url(http://oi67.tinypic.com/2niy905.jpg);
position:absolute;z-index:-1;
background-repeat: repeat-x;
position: relative;
animation: animatedBackground 80s linear infinite;
}
<div id="animate-area"></div>
<div id="animate-area2"></div>
Related
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>
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>
I have tried a lot of different ways using animation keyframes. I cannot seem to be able to do it.
I basically want my background animate left to right and repeat, like a marquee but as my background.
It seems like the only solution for me is to make a gif for my background, but that is really time extensive for me.
to avoid jumps in the animation (once it reachs the end and start again) I would move the image with repeat-x to an exagerated amount of x coordenates like this:
html {
margin:0;padding:0; height:100%;
}
body {
height:100%;
background-image:url(https://i.imgur.com/aCDecXL.jpg);
background-size: auto 100%;
overflow:hidden;
background-repeat:repeat-x;
animation: scroll 700000s infinite linear;
}
#keyframes scroll {
from { background-position: 0%; }
to { background-position: 90000000%; }
}
Try this.
#animate-area {
width: 560px;
height: 400px;
background-image: url('http://labs.designoptimizer.net/snip/bg-clouds.png');
background-position: 0px 0px;
background-repeat: repeat-x;
animation: animatedBackground 40s linear infinite;
}
#keyframes animatedBackground {
from { background-position: 0 0; }
to { background-position: 100% 0; }
}
<div id="animate-area"></div>
Use animation keyframe to make it work
.background{
background: url(https://dummyimage.com/1500x700/);
width: 560px;
height: 400px;
background-position: 0px 0px;
background-repeat: repeat-x;
background-size: cover;
animation: animation_back 2s linear infinite;
}
#keyframes animation_back {
from { background-position: 0 0; }
to { background-position: 200% 0; }
}
<div class="background">
</div>
This question already has answers here:
Transparent text cut out of background
(14 answers)
Closed 7 years ago.
I have an animated background and I would really like the effect of my text to be cut out and show the background.
I have seen example where you can attach a background image and set background color to the same layer and then show the image in the text but not any examples where the layer underneath was revealed. Is it possible?
So in this snippet the white text would be cut out and you could see the gradient changing through the hole.
body {
background: linear-gradient(270deg, #000, #fff);
background-size: 400% 400%;
-webkit-animation: AnimationName 5s ease infinite;
-moz-animation: AnimationName 5s ease infinite;
animation: AnimationName 5s ease infinite;
}
#-webkit-keyframes AnimationName {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
#-moz-keyframes AnimationName {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
#keyframes AnimationName {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.container{
width: 400px;
height: 200px;
background-color: darkred;
margin: auto;
color: #fff;
font-size: 80px;
font-weight: 900;
text-align: center;
}
<div class="container">TO BE CUT OUT</div>
jsfiddle: https://jsfiddle.net/nmhmxkyj/
You can use SVG and apply <mask>
#import url(https://fonts.googleapis.com/css?family=Lato:900);
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
background: url('http://science-all.com/images/mountain/mountain-03.jpg');
background-size: cover;
background-position: center center;
}
svg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-45%, -50%);
}
text {
font-size: 80px;
text-anchor: middle;
font-family: 'Lato', sans-serif;
}
<svg width="450px" height="250px">
<mask id="mask" height="100%" width="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"></rect>
<text>
<tspan x="45%" dy="1.2em">TO BE</tspan>
<tspan x="45%" dy="1.1em">CUT OUT</tspan>
</text>
</mask>
<rect width="100%" height="100%" mask="url(#mask)" fill="#8B0000"></rect>
</svg>
My previous answer was the only way I could find to complete this in pure CSS. However, this is possible using javascript and a canvas. Would this satisfy your question?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.save();
ctx.beginPath();
ctx.fillStyle = "darkred";
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.font = "70pt Arial";
ctx.globalCompositeOperation = "xor";
ctx.beginPath();
ctx.fillText("To Be", 60, 80);
ctx.fillText("Cut Out", 35, 180);
ctx.fill();
ctx.restore();
body {
background: linear-gradient(270deg, #000, #fff);
background-size: 400% 400%;
-webkit-animation: AnimationName 5s ease infinite;
-moz-animation: AnimationName 5s ease infinite;
animation: AnimationName 5s ease infinite;
}
#-webkit-keyframes AnimationName {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
#-moz-keyframes AnimationName {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
#keyframes AnimationName {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
<canvas id="canvas" width="400px" height="200px"></canvas>
JSFiddle: https://jsfiddle.net/p98waufL/
How do i use a checkbox to change/toggle an animation play state from play to pause ( do i have to use js), I know it needs a bit more work but i am kind of stuck at this point as I know little to no javascript. ( any help would be greatly appreciated :) ) this is what I have so far:
<body id="body" onLoad="reset(); return true;">
<div id="wrapper">
<div id="cloud">
<div id="cloud1">
<header id="topheader">
<input type="checkbox" id="toggle" name="toggle"/>
<label for="toggle"></label>
</header>
</div>
</div>
</div>
</body>
#cloud{
background-image: url("../image/clouds.png");
background-size: 200% 200%;
background-position: -50% -50%;
-webkit-animation: cloud 120s ease-in-out infinite alternate;
-moz-animation: cloud 120s ease-in-out infinite alternate;
-o-animation: cloud 120s ease-in-out infinite alternate;
animation: cloud 120s ease-in-out infinite alternate;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
#-webkit-keyframes cloud {
0%{
background-size: 200% 200%;
background-position: -50% -50%;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
}
100%{
background-size: 100% 100%;
background-position: 50% 50%;
}
}
#-moz-keyframes cloud {
0%{
background-size: 200% 200%;
background-position: -50% -50%;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
}
100%{
background-size: 100% 100%;
background-position: 50% 50%;
}
}
#keyframes cloud {
0%{
background-size: 200% 200%;
background-position: -50% -50%;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
}
100%{
background-size: 100% 100%;
background-position: 50% 50%;
}
}
#-o-keyframes cloud {
0%{
background-size: 200% 200%;
background-position: -50% -50%;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
}
100%{
background-size: 100% 100%;
background-position: 50% 50%;
}
}
#cloud1{
background-image: url("../image/clouds1.png");
background-size: 200% 200%;
background-position: 150% 150%;
-webkit-animation: cloud1 150s ease-in-out infinite alternate;
-moz-animation: cloud1 150s ease-in-out infinite alternate;
-o-animation: cloud1 150s ease-in-out infinite alternate;
animation: cloud1 150s ease-in-out infinite alternate;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
#-webkit-keyframes cloud1 {
0%{
background-size: 200% 200%;
background-position: 150% 150%;
opacity: .8;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
opacity: .5;
}
100%{
background-size: 100% 100%;
background-position: -50% -50%;
opacity: .3;
}
}
#-moz-keyframes cloud1 {
0%{
background-size: 200% 200%;
background-position: 150% 150%;
opacity: .8;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
opacity: .5;
}
100%{
background-size: 100% 100%;
background-position: -50% -50%;
opacity: .3;
}
}
#keyframes cloud1 {
0%{
background-size: 200% 200%;
background-position: 150% 150%;
opacity: .8;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
opacity: .5;
}
100%{
background-size: 100% 100%;
background-position: -50% -50%;
opacity: .3;
}
}
#-o-keyframes cloud1 {
0%{
background-size: 200% 200%;
background-position: 150% 150%;
opacity: .8;
}
50%{
background-size: 150% 150%;
background-position: 0% 0%;
opacity: .5;
}
100%{
background-size: 100% 100%;
background-position: -50% -50%;
opacity: .3;
}
}
input[type="checkbox"] {
display: none;
}
input[type="checkbox"] + label:before{
content: "";
position: relative;
float: right;
margin: 1px;
padding: 2px;
background-image: url("../icons/pauseButton.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
height: 27px;
width: 27px;
border-radius: 2px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
background-color: rgba(110, 0, 250, .5);
}
input[type="checkbox"]:checked + label:before{
content: "";
position: relative;
float: right;
margin: 1px;
padding: 2px;
background-image: url("../icons/playButton.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
height: 27px;
width: 27px;
border-radius: 2px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
background-color: rgba(110, 0, 250, .5);
}
You can use animation-play-state, then use jQuery to toggle a class on the element you are animating, where this is set to paused
The animation-play-state CSS property determines whether an animation
is running or paused. You can query this property's value to determine
whether or not the animation is currently running; in addition, you
can set its value to pause and resume playback of an animation.
Resuming a paused animation will start the animation from where it
left off at the time it was paused, rather than starting over from the
beginning of the animation sequence.
E.g, the class could simply be:
.paused{
animation-play-state: paused;
}
The alternative would be to set the CSS property directly.
The simplest way to then alter with Javascript depending on checkbox state would likely to be to leverage jQuery (I appreciate you havent mentioned it) to do, e.g.:
$('#toggle').click(function(e) {
$('#cloud').toggleClass('paused', $('#toggle').is(':checked'));
});