How to make a permanent change background-position in js? - javascript

I know how to run the animation from point A to point B, so to speak, but do not know how to run continuously in a circle. Below is a small code prepared:
.bg {
display: block;
position: absolute;
width: 100%;
height: 100%;
background: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg) top left/30%;
animation: bg 2s cubic-bezier(0, -0.02, 1, 0.99);
}
#keyframes bg {
0% {
background-position: left -100px;
}
100% {
background-position: left 0px;
}
}
<div class="bg"></div>
help with script

If by:
run continuously in a circle
You mean run animation in a loop, then you can add the infinite animation-iteration-count property. In the shortcode you can just add infinite to your animation property. See demo:
.bg {
display: block;
position: absolute;
width: 100%;
height: 100%;
background: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg) top left/30%;
animation: bg 2s cubic-bezier(0, -0.02, 1, 0.99) infinite;
}
#keyframes bg {
0% {
background-position: left -100px;
}
100% {
background-position: left 0px;
}
}
<div class="bg"></div>
Edit: jQuery Solution
With jQuery you can use the animate() function to achieve the same effect.
// bg animation function
function bgAnimate(speed) {
// define bg div
var el = $('.bg');
// get current background y-axis position and convert to integer (strips `px`)
var posY = parseInt(el.css("background-position-y"));
// animate element
el.animate({
'background-position-y': posY + 100 // add 100px
},{
duration: speed,
easing: 'linear',
complete: function() {
bgAnimate(speed); // repeat aniamtion (loop)
}
});
}
bgAnimate(1000); // call function
html, body {padding: 0;margin: 0;}
.bg {
display: block;
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-image: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="bg"></div>

Related

How to add CSS transitions to Automatic Slider?

I am trying to apply 'opacity / sliding to left' for my automatic slider but I couldn't make it. Please help me with this.
let images = ["images/a.jpg", "images/b.jpg", "images/c.jpg", "images/d.jpg", ];
let i = 0;
function changeImg() {
document.querySelector("#slider img").src = images[i];
if (i < images.length - 1) {
i++;
} else {
i = 0;
}
setTimeout("changeImg()", 1000);
}
onload(changeImg());
#slider img {
width: 100vw;
height: 60vh;
transition: opacity 2s ease-out;
}
<section id="slider">
<img name="slide" width="400" height="200" />
</section>
The initial requirement is for the image to fade and another one be shown.
This can be achieved by placing the images one on top of the other (position absolute) and opacity 0 with a transition set on opacity. When it is a particular images turn to be shown the image before it is set to opacity 0 and the new image has its opacity set to 1.
let images = ["https://picsum.photos/id/1015/300/300", "https://picsum.photos/id/1016/200/300", "https://picsum.photos/id/1018/300/200.jpg", "https://picsum.photos/id/1022/400/300", ];
const slider = document.querySelector('#slider');
const imgEls = [];
images.forEach(image => {
let imgEl = document.createElement('img');
imgEl.src = image;
imgEls.push(imgEl);
slider.appendChild(imgEl);
});
let i = 0;
function changeImg() {
imgEls[i].style.opacity = 0;
if (i < images.length - 1) {
i++;
} else {
i = 0;
}
imgEls[i].style.opacity = 1;
setTimeout("changeImg()", 1000);
}
window.onload = changeImg;
#slider {
width: 100vw;
height: 60vh;
position: relative;
isplay: felx;
justify-content: center;
align-items: center;
}
#slider img {
display: inline-block;
width: 100vw;
height: 60vh;
object-fit: contain;
transition: opacity 2s ease-out;
opacity: 0;
position: absolute;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="slider">
<https://stackoverflow.com/questions/69870264/how-to-add-css-transitions-to-automatic-slider#img name="slide" width="400" height="200" />
</section>
While the action seems to correspond to what was discussed in the comments it doesn't make a real 'slider' and the question also talks of sliding to the left using CSS.
This snippet takes a slightly different approach to the question's code in that once the initial set up of the slides has been done using Javascript everything else is done via CSS. This has the advantage that it's possible the system can just hand the animation to the GPU without needing to interrupt back to the main program on a timeout.
Each image is located at left 100% (ie just off screen to the right) and it is given the same animation as the other - move to the center, wait and then move out to the left - opacity fading in and out respectively. The images however start animating at staggered times so the sliding looks continuous.
const slider = document.querySelector('#slider');
const images = ["https://picsum.photos/id/1015/300/300", "https://picsum.photos/id/1016/200/300", "https://picsum.photos/id/1018/300/200", "https://picsum.photos/id/1022/400/300"];
let div;
let count = 0;
images.forEach(image => {
div = document.createElement('div');
div.style.animationDelay = (count * 2) + 's';
count++;
div.style.setProperty('--img', 'url(' + image + ')');
slider.appendChild(div);
});
slider.style.setProperty('--n', count);
#slider {
overflow: hidden;
width: 100vw;
height: 60vh;
position: relative;
}
#slider div {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: 0;
display: inline-block;
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
background-image: var(--img);
animation-name: slide;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-duration: calc(var(--n) * 2s);
animation-fill-mode: forwards;
}
#keyframes slide {
0% {
opacity: 0;
transform: translateX(100vw);
}
12.5% {
opacity: 1;
transform: translateX(0);
}
25% {
opacity: 1;
transform: translateX(0);
}
37.5%,
100% {
opacity: 0;
transform: translateX(-100vw);
}
}
<div id="slider"></div>
Note that the keyframes settings assume 4 images. The % values would have to be changed for more or fewer. Unfortunately CSS does not allow variables as % values in keyframes so the JS would ideally find the number of images and create the correct keyframes.

problem on onclick() event for more than one clicks done on a div

i have an html page where,when hovered over the first image a second image fades in/is shown.The first image has an onclick() event which performs a transition of rotating the image and scaling it by some number.During the transition, the first image disappears and some text appears on the same place(area of the div tag of the first image).I perform the transition through javascript and the hovering animation using css. Now when i click on the text(or the area of the div tag) the transition must reverse back i.e., the div area must be as it was before clicking(even with the hovering working.). I would like to know the answer through pure javascript please.
Thank you in advance.
timesclicked = 0;
document.getElementById("hoverImage").addEventListener("click", function()
{
var x = document.getElementById('container');
timesclicked+=1;
if(timesclicked%2!=0)
{
//obj.style.opacity = '0.5';
x.style.transform = 'rotateZ(-360deg) scale(1.4)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<div style="font-size:16px; font-family: monospace; font-weight:bold; text-align:center; "> My Hero Academia, abbreviated as HeroAca is a Japanese superhero manga series written and illustrated by Kōhei Horikoshi. It has been serialized in Weekly Shōnen Jump since July 2014, and, as of February 2019, 22 volumes have been collected in tankōbon format.</div>'},'1300');
}
else
{
x.style.transform = 'rotateZ(-45deg) scale(1)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<img src="https://picsum.photos/300">'},'500');
}
});
img
{
width: 300px;
height: 300px;
}
#mainImage,#hoverImage
{
left: 0px;
position: absolute;
top: 0px;
}
#hoverImage
{
opacity: 0;
transition: opacity 0.4s 0.1s ;
}
#hoverImage:hover
{
opacity: 1;
}
#container
{
background: url(https://picsum.photos/300);
background-size: cover;
width: 300px;
height: 300px;
position: absolute;
top:20%;
left:40%;
transform: rotateZ(-45deg);
}
#container:before
{
content: "";
display: block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -1;
background-color: rgba(255, 255, 255, 0.6);
}
<div id="container" >
<img id="mainImage" src="https://picsum.photos/300">
<img id="hoverImage" src="https://picsum.photos/300">
</div>
As much as i know, I think the second clicking event is not happening because the eventlistener is on the hoverImage. I need a way to run the else part of the code somehow.
It looks like there are a few problems with your code, and you're going to have some debugging to do. That said, try this for a strategy:
Put your on-click event on the #container.
Put all the styling and transitioning details in the css. Your javascript will just add and remove a class from the #container.
Don't track the number of clicks unless you need it for something else. Have your if statement check for the presence or absence of the class you're toggling. (Or use an explicit toggle instead of an if-else block.)
Don't add and remove the text and background in the javascript, put them both in the HTML and control their visibility using the CSS.
edit:
People asked for examples and clarification. I'm stealing some of this from other people's answers.
I'm not completely sure I've understood OP's intentions correctly, and there are some rough-around-the-edgues details (like the cursor when you hover before clicking), but I think this should serve as an example:
let container = document.getElementById("container");
container.addEventListener("click", function(){
container.classList.toggle("selected");
});
#mainImage, #hoverImage, #selectedText {
width: 300px;
height: 300px;
left: 0px;
position: absolute;
top: 0px;
}
#hoverImage {
opacity: 0;
transition: opacity 0.4s 0.1s;
}
#container:hover > #hoverImage {
opacity: 1;
}
#container {
width: 300px;
height: 300px;
position: absolute;
top:20%;
left:40%;
transform: rotateZ(-45deg);
transition: all 1.5s ease-in-out;
}
#container.selected {
transform: rotateZ(-360deg) scale(1.4);
}
#container:before {
content: "";
display: block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -1;
background-color: rgba(255, 255, 255, 0.6);
}
#selectedText {
font-size:16px;
font-family: monospace;
font-weight:bold;
text-align:center;
background: url(https://picsum.photos/300?text);
background-size: cover;
opacity: 0;
transition: opacity 0.1s 0.5s;
}
#container.selected > #selectedText {
opacity: 1;
transition: opacity 0.1s 1.3s;
}
<div id="container">
<img id="mainImage" src="https://picsum.photos/300?main">
<img id="hoverImage" src="https://picsum.photos/300?hover">
<div id="selectedText">
My Hero Academia, abbreviated as HeroAca is a Japanese superhero
manga series written and illustrated by Kōhei Horikoshi. It has been
serialized in Weekly Shōnen Jump since July 2014, and, as of
February 2019, 22 volumes have been collected in tankōbon format.
</div>
</div>
you can add the click event listener on the container div.
timesclicked = 0;
document.getElementById("container").addEventListener("click", function()
{
var x = document.getElementById('container');
timesclicked+=1;
if(timesclicked%2!=0)
{
//obj.style.opacity = '0.5';
x.style.transform = 'rotateZ(-360deg) scale(1.4)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<div style="font-size:16px; font-family: monospace; font-weight:bold; text-align:center; "> My Hero Academia, abbreviated as HeroAca is a Japanese superhero manga series written and illustrated by Kōhei Horikoshi. It has been serialized in Weekly Shōnen Jump since July 2014, and, as of February 2019, 22 volumes have been collected in tankōbon format.</div>'},'1300');
}
else
{
x.style.transform = 'rotateZ(-45deg) scale(1)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<img src="https://picsum.photos/300">'},'500');
}
});
img
{
width: 300px;
height: 300px;
}
#mainImage,#hoverImage
{
left: 0px;
position: absolute;
top: 0px;
}
#hoverImage
{
opacity: 0;
transition: opacity 0.4s 0.1s ;
}
#hoverImage:hover
{
opacity: 1;
}
#container
{
background: url(https://picsum.photos/300);
background-size: cover;
width: 300px;
height: 300px;
position: absolute;
top:20%;
left:40%;
transform: rotateZ(-45deg);
}
#container:before
{
content: "";
display: block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -1;
background-color: rgba(255, 255, 255, 0.6);
}
<div id="container" >
<img id="mainImage" src="https://picsum.photos/300">
<img id="hoverImage" src="https://picsum.photos/300">
</div>
</style>
if I understand your problem correctly, I think you just need to move the transition styles into your CSS
x.style.transition = 'all 1.5s ease-in-out';

How to make image move in a frame infinitely?

okay so I have this right here:
html:
<div class="object">
<img src="https://www.direktorenhaus.com/wp-content/uploads/2018/03/Kabali-After-Puja-6-1-800x533.jpg" alt="pic">
</div>
css:
.object {
animation: MoveLeftRight 10s linear infinite;
position: absolute;
top: 0;
right: 0;
}
#keyframes MoveLeftRight {
0%, 100% {
right: 0;
}
50% {
right: 300px;
}
}
demo: https://jsfiddle.net/kte1ar3p/
but instead of it moving left and right, right to left all the time, i want to to like go through... i.e when it goes from e.g right to left, it will come out again from right to left. i dont know if this makes sense as I am explaining...
like moving a big picture into a small frame.
EDIT:
I got this so far, which should do with a little bit of playing around. thank you. https://jsfiddle.net/rgsnwb79/
Change CSS
.object{
position: relative;
width: 300px;
height: 280px;
overflow: hidden;
}
.object img {
animation: MoveLeftRight 10s linear infinite;
position: absolute;
top: 0;
right: 0;
}
#keyframes MoveLeftRight {
0%, 100% {
right: 0;
}
50% {
right: -50%;
}
}
https://jsfiddle.net/kte1ar3p/2/
Considering you want to repeat the display of the image and its movement... What if you animated it like sliding the image off of itself (like a deck of cards)?
HTML
<div class="object">
<img class="slide" src="https://images.freecreatives.com/wp-content/uploads/2016/04/Abstract-Patterns-For-Free.jpg" alt="pic">
</div>
CSS
body {
margin: 0;
}
.object {
background-image: url("https://images.freecreatives.com/wp-content/uploads/2016/04/Abstract-Patterns-For-Free.jpg");
width: 100vw;
height: 100vh;
}
.slide {
animation: MoveLeftRight 3s linear infinite;
position: absolute;
top: 0;
left: 0;
}
#keyframes MoveLeftRight {
0% { left: 0; }
50% { left: 50%; }
100% { left: 100%; }
}
https://jsfiddle.net/mittenmoon72/kte1ar3p/27/
If you're wanting a carousel, I'd just use one of the many JavaScript carousel libraries out there.

3D wheel spinning effect in css

I am trying to build a simple web element that resembles the wheel contestants spin on The Price is Right (sample video). My question is: is there a more efficient way to achieve this effect than what I've cobbled together below?
My first attempt at this functionality basically decrements the translateY property of an element that contains the elements to be spun [codepen]:
setInterval(shiftCards, 100)
var translateY = -60,
cardIdx = 0,
startCards = 60,
wrap = document.querySelector('.wrap');
for (var i=0; i<startCards; i++) {
addCard()
}
function addCard() {
var div = document.createElement('div');
div.className = 'card';
div.style.top = (cardIdx * 12) + 'px';
wrap.appendChild(div);
cardIdx++;
}
function shiftCards() {
wrap.style.transform = 'translateY(' + translateY + 'px)';
translateY -= 12;
var cards = wrap.querySelectorAll('.card');
if (cards.length >= startCards) {
cards[0].parentNode.removeChild(cards[0]);
addCard();
}
}
.cards {
width: 80px;
height: 200px;
overflow: hidden;
background: #aaa;
}
.wrap {
position: relative;
transition: transform .25s;
}
.card {
width: 100%;
height: 10px;
margin: 2px 0;
background: red;
position: absolute;
left: 0;
right: 0;
}
<div class='cards'>
<div class='wrap'>
</div>
</div>
Is there a more efficient way to achieve this functionality? Can I create an element with n children and actually just spin them in the Z-dimension, rather than create an artificial spin as I've done above? Any guidance others can offer on this question will be very appreciated!
You can use css-animations for this: (They are probably more efficient)
/* only alignment */
body, html {
height: 100%;
margin: 0;
padding: 0;
}
.wrapper {
display:flex;
justify-content:center;
align-items:center;
height: 100%;
}
/* actual spinning */
img {
animation: spin 5s infinite linear;
/*
spin: the keyframes (=animation) we want to have
5s: how long it should take for one iteration
infinite: how often should it repeat
linear: the easing between the different key frames You can also try 'ease'
*/
}
#keyframes spin {
0% {transform: translateY(-60px);} /* Starting point */
100% {transform: translateY(-360px);} /* end point */
}
#-webkit-keyframes spin {
0% {transform: translateY(-60px);}
100% {transform: translateY(-360px);}
}
<div class="wrapper">
<img src="https://www.placecage.com/300/100" class="spin">
</div>

When background image scaled, it starts to flicker in Chrome

I have a div with a background image on it. When it has simple transform scale animation, it starts to flicker in Google Chrome and Opera.
Here is a simple exmple:
http://codepen.io/anon/pen/bWpNYq
CSS:
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-color: #f00;
background-position: 50% 50%;
background-image: url(".....jpg");
background-size: cover;
}
Script:
TweenLite.set('div', {
backfaceVisibility: 'hidden',
perspective: 1000
});
TweenLite.fromTo('div', 10, {
scale: 1.1
}, {
scale: 1
});
When the image is a simple img element, the same scale animation works fine. The transition is smooth:
http://codepen.io/anon/pen/pPyvdp
The examples use GASP for animations. I need a solution which use GSAP to scale the div with better result.
Do you any idea how to make it smooth with background image?
Try this:
Add transition: all 1s linear; so it scale smoothly.
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
background-size: cover;
transition: all 1s linear;
}
Hey maybe you can try out this css animation. For better browser support add
-webkit-animation
-moz-animation
-o-animation
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
background-size: cover;
-webkit-animation: animate 5s forwards;
animation: animate 5s forwards;
}
#-webkit-keyframes animate {
0% { transform: scale(1); }
100% { transform: scale(1.1); }
}
#keyframes animate {
0% { transform: scale(1); }
100% { transform: scale(1.1); }
}
<div>
</div>
CSS3 allows you to add native transition to your transformations. Try to use code below:
document.body.addEventListener('click', function(){
var div = document.getElementById('img');
div.style.transform = 'scale(.5)';
})
body {
height: 100vh;
overflow: hidden
}
div {
width: 100%;
height: 100%;
background-position: 50% 50%;
background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
background-size: cover;
transition: transform 30s;
}
<div id="img"></div>
It uses css property "transition" and starts transition on body click.
Just use css, way better. If you open up your inspector you'll see that your tweenlite code is setting/ updating the style attribute of your div very fast with this piece of code: transform: translate3d(0px, 0px, 0px) scale(1.00212, 1.00212);.
This is JS calculating something and then telling CSS what to do (very basic explanation). CSS can do this on it's own. Why do you want to stick with your GSAP engine so badly?

Categories

Resources