How to smoothly change background (animate) in JavaScript? - javascript

I have 30 images that make together a full turn of a 3D model. I want to display the animation in browser. I can not use CSS animation, which otherwise worked good. The problem with JavaScript is flickering when the next image loads. Is there any way to make it smoother?
<div id="image" style="width: 1920px; height: 1080px;">
</div>
<script>
let suffix;
let i = 0;
let image = document.getElementById("image");
function setSuffix(){
suffix = ("0" + (i+1)).slice(-2);
i++;
i = i % 30;
image.style.background = "URL('" + suffix + ".jpg')";
}
setInterval(setSuffix, 1000);
</script>

Perhaps you can use a supplemental image, load it, then bring it to the front using z-index. Something like:
let suffix;
let i = 0;
let image1 = document.getElementById("image1");
let image2 = document.getElementById("image2");
// TIP: Remove these
let url1 = "https://scontent-iad3-1.xx.fbcdn.net/v/t1.0-9/41667401_10155851253461762_5185170392754421760_n.png?_nc_cat=101&oh=beb534388a04dd5ea101bc9560fa5e24&oe=5C1F4FAD";
let url2 = "https://scontent-iad3-1.xx.fbcdn.net/v/t1.0-9/34661720_10155632057856762_4698625317663670272_n.jpg?_nc_cat=106&oh=dd89a8d15e587dba4b7fe8b3ea38143e&oe=5C1E5CC0";
function setSuffix(){
// TIP: Uncomment this
//imageUrl = ("0" + (i+1)).slice(-2) + ".jpg";
if (i % 2 === 0) {
imageUrl = url1; // TIP: Remove this.
image1.style.background = `URL('${imageUrl}')`;
image1.style.zIndex = "1";
image2.style.zIndex = "0";
} else {
imageUrl = url2; // TIP: Remove this.
image2.style.background = `URL('${imageUrl}')`;
image2.style.zIndex = "1";
image1.style.zIndex = "0";
}
i++;
}
setInterval(setSuffix, 1000);
#image1, #image2{
position:absolute;
top: 0px;
left: 0px;
}
<div id="image1" style="width: 1920px; height: 1080px;"></div>
<div id="image2" style="width: 1920px; height: 1080px;"></div>

Related

How to repeat randomised img endlessly on javascript?

I have a function that render random image without repeating, but it stops working when the array of images has come to an end, my goal is to restart function with another random order of images, so function can work infinite. I've read another questions, but didn't find something appropriate to me case.
Here is html part:
<div class="card">
<div class="front" onClick="pickimg();return false;"><img
src="1.jpg" alt=""></div>
<div class="back"><img src="2.jpg" name="randimg"></div>
</div>
Css (just in case):
.card {
width: 200px;
height: 300px;
position: relative;
perspective: 1000px;
cursor: pointer;
margin: 0 50px;
}
.front, .back {
width: 100%;
height: 100%;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
transition: 1s;
backface-visibility: hidden;
border-radius: 10px;
}
.front {
transform: rotateY(360deg);
}
.back {
transform: rotateY(180deg);
}
And JS:
var cards = document.querySelectorAll('.card')
Array.from(cards).forEach(function(card) {
card.addEventListener('click', function() {
Array.from(card.querySelectorAll('.back, .front')).forEach(function(el) {
['back', 'front'].forEach(function(s) {
el.classList.toggle(s)
});
});
});
});
var usedImages = {};
var usedImagesCount = 0;
function pickimg(){
var imagenumber = 3;
var randomnumber = Math.random();
var rand1 = Math.round( (imagenumber-1) * randomnumber) + 1;
images = new Array();
images[0] = "";
images[1] = "3.jpg";
images[2] = "4.jpg";
images[3] = "2.jpg";
var image = images[rand1];
if (!usedImages[rand1]){
document.randimg.src = images[rand1];
usedImages[rand1] = true;
usedImagesCount++;
if (usedImagesCount === images.length){
usedImagesCount = 0;
usedImages = {};
}
} else {
pickimg();
}
}
Thank you for your help.
You could try something like this:
let img = [1,2,3,4,5];
function switchImage () {
for(; ; ){
let x = Math.random() * 10;
if(typeof img[Math.round(x)] !== 'undefined') {
img.splice(x, 1);
break;
}
}
console.log(img);
if (img.length > 0){
setTimeout(() => switchImage (),1000);
}
}
switchImage();
This is a simplified example where every second the function calls itself again and a new image is picked from the image array. The old image is cut out of the array and the function will stop calling itself when every picture is shown.
Try this -
int lastIndex = Math.round(Math.random()*(imagenumber - 1)) + 1;
function pickImg(){
let imagenumber = 3;
int currIndex = Math.round(Math.random()*(imagenumber - 1)) + 1;
images = new Array();
images[0] = "2.jpg";
images[1] = "3.jpg";
images[2] = "4.jpg";
if (lastIndex !== currIndex) {
document.randimg.src = images[currIndex];
lastIndex = currIndex;
}
else {
pickImg();
}
}
If you didn't get any image displayed that means you have to deal with when images[index] returns undefined.
Inshort you need to have index in images always equal to some value.
How about simple like this does this work for you? at least it will not give you same number a row
var imgArr = [1, 2, 3, 4, 5, 6] // imagine this is your img
var lastImgIndex;
function loadImg() {
var RandomIndex = Math.floor((Math.random() * imgArr.length) + 1);
if (lastImgIndex != RandomIndex) {
$('span').text(RandomIndex + ' index of img show');
lastImgIndex = RandomIndex;
} else {
loadImg();
}
}
loadImg();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span></span>

Image Slider with counter

I know this question is maybe a bit boring. But I'm searching now for serveral hours and find no way to combine the solutions I found on the Internet.
So I hope someone here would like to help me out.
I have a simple Image slider and I need a counter that says maybe "Image 2 of 3".
As I said, there are a lot of solutions on the internet but I'm not able to implement them to my code.
This is the code Im working with:
HTML
<div class="slider">
<img src="http://placehold.it/250x500" class="active"/>
<img src="http://placehold.it/200x500" />
<img src="http://placehold.it/100x500" />
</div>
<!-- ARROW AND COUNTER -->
<div>
<img src="assets/img/arrow-prev.png" class="prev" alt="Prev Arrow"/>
<span id="counter"></span>
<img src="assets/img/arrow-next.png" class="next" alt="Next Arrow"/>
</div>
CSS
.slider{
height: 51vh;
overflow: hidden;
}
.slider img{
display: none;
height: 51vh;
}
.slider img.active{
display: inline-block;
}
.prev, .next{
cursor: pointer;
}
JAVASCRIPT
$(document).ready(function () {
$('.next').on('click', function () {
var currentImg = $('.active');
var nextImg = currentImg.next();
if (nextImg.length) {
currentImg.removeClass('active').css('z-index', -10);
nextImg.addClass('active').css('z-index', 10);
}
});
$('.prev').on('click', function () {
var currentImg = $('.active');
var prevImg = currentImg.prev();
if (prevImg.length) {
currentImg.removeClass('active').css('z-index', -10);
prevImg.addClass('active').css('z-index', 10);
}
});
});
It would be really great if someome can help me!
So basically you should just keep track of all images and the index of the currently displayed image. Something like the code below could do that.
$(document).ready(function () {
// Get images.
var images = $('.slider > img');
// Set starting index.
var index = images.index($('.active'));
$('#counter').text((index + 1) + ' of ' + images.length);
$('.next').on('click', function () {
var currentImg = $('.active');
var nextImg = currentImg.next();
if (nextImg.length) {
currentImg.removeClass('active').css('z-index', -10);
nextImg.addClass('active').css('z-index', 10);
// Find the index of the image.
var index = images.index(nextImg);
$('#counter').text((index + 1) + ' of ' + images.length);
}
});
$('.prev').on('click', function () {
var currentImg = $('.active');
var prevImg = currentImg.prev();
if (prevImg.length) {
currentImg.removeClass('active').css('z-index', -10);
prevImg.addClass('active').css('z-index', 10);
// Find the index of the image.
var index = images.index(prevImg);
$('#counter').text((index + 1) + ' of ' + images.length);
}
});
});
Link to jsfiddle example.
Explanation: I've added a index variable that checks the active class position:
var index = images.index($('.active'));
$('#counter').text("Image " + (index + 1) + ' of ' + images.length);
Working code:
So Have a look at this code because this should work fine!
$(document).ready(function() {
var images = $('.slider > img');
var index = images.index($('.active'));
$('#counter').text("Image " + (index + 1) + ' of ' + images.length);
$('.next').on('click', function() {
var currentImg = $('.active');
var nextImg = currentImg.next();
if (nextImg.length) {
currentImg.removeClass('active').css('z-index', -10);
nextImg.addClass('active').css('z-index', 10);
var index = images.index(nextImg);
$('#counter').text("Image " + (index + 1) + ' of ' + images.length);
}
});
$('.prev').on('click', function() {
var currentImg = $('.active');
var prevImg = currentImg.prev();
if (prevImg.length) {
currentImg.removeClass('active').css('z-index', -10);
prevImg.addClass('active').css('z-index', 10);
var index = images.index(prevImg);
$('#counter').text("Image " + (index + 1) + ' of ' + images.length);
}
});
});
.slider {
height: 51vh;
overflow: hidden;
}
.slider img {
display: none;
height: 51vh;
}
.slider img.active {
display: inline-block;
}
.prev,
.next {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slider">
<img src="https://placehold.it/450x500/red" class="active" />
<img src="https://placehold.it/450x500/r" />
<img src="https://placehold.it/450x500" />
</div>
<!-- ARROW AND COUNTER -->
<div>
<img src="https://placehold.it/50/red" class="prev" alt="Prev Arrow" />
<span id="counter"></span>
<img src="https://placehold.it/50/blue" class="next" alt="Next Arrow" />
</div>
I hope this is the solution you have expected. For any further questions to my answer - let me know :)
Without jQuery, just plain javascript.
With css opacity transition.
https://jsfiddle.net/uatthqjp/3/
const $images = document.querySelectorAll('img');
// `Array.from` for backward compatibility
// to convert `$images` into a real array
// so you can use `forEach` method on it
// use in conjunction with a polyfill
// for example: www.polyfill.io
const images = Array.from($images);
const $buttons = document.querySelector('.buttons');
// counter for current img
let current = 0;
// listen to click events on `$buttons` div
$buttons.addEventListener('click', function(e){
// loop through all images
images.forEach(function(img){
// hide all images
img.classList.remove('active');
});
// if the current clicked button
// contain the class "next"
if (e.target.classList.contains('next')) {
// increment counter by 1
current++;
// reset the counter if reach last img
if (current >= images.length) {
current = 0;
}
// show current img
images[current].classList.add('active');
}
// if the current clicked button
// contain the class "prev"
else {
// decrease counter by 1
current--;
// if "prev" is pressed when first img is active
// then go to the last img
if (current < 0) {
current = images.length - 1;
}
// show current img
images[current].classList.add('active');
}
});
img {
position: absolute;
top: 40px;
opacity: 0; /* hide images */
transition: opacity 1s ease-in-out;
}
.active {
opacity: 1;
}
<img class="active" src="https://dummyimage.com/100x100/e62020/fff&text=IMG1" alt="img1">
<img src="https://dummyimage.com/100x100/20e679/fff&text=IMG2" alt="img2">
<img src="https://dummyimage.com/100x100/4120e6/fff&text=IMG3" alt="img3">
<div class="buttons">
<button class="prev">Prev</button>
<button class="next">Next</button>
</div>
If you look for the easiest solution there is one. All that code added by other users look difficult for me. You can add simple html code with text to each slide and write "1/4", "2/4" etc. Even if you have 10 slides it may be easier than to implement huge jquery or javascript.
The example can be found here W3Schools slideshow
Another very common solution is to use bullet navigator. Many global companies use this solution because it is very easy to understand for everybody. Example - if you have 5 slides you have 5 bullets in the center bottom part of an image. If slide #3 is visible at the moment, third bullet changes color to indicate that you are on slide #3.
There are a few websites that create the entire html/css/js for sliders and you can customize it as you want.
Example of a page: Jssor.com

How to stop Looping - Javascript 100%

I was hoping someone could help me figure this out. I will list the code, and it works just fine, as it is an animation. However, when I check it out in the console it wont stop looping even though it hit the last item in the array. The image itself stops, but if you view the console it shows it looping.
Here is the code, have at it!
var position_X = ["0px", "-525px", "-1050px", "-1575px", "-2100px", "-2625px", "-3150px", "-3675px", "-4200px", "-4725px", "-5250px", "-5775px", "-6300px", "-6825px", "-7350px"];
var _lock = document.getElementById('hi');
// console.log(_lock);
_lock.style.border = "1px solid black";
_lock.style.backgroundImage = "url('http://handbagmanufacturing.com/wp-content/CDN/images/lock.png')";
function lockAnimation(){
setInterval(function(){
var _count = position_X.length;
for(var i = 0; i < _count; i++){
if(i == _count) break;
_lock.style.backgroundPosition = position_X[i] + " 263px";
console.log("Here is the background positions : " + i + ") " + position_X[i]);
}
}
, 100);
}
#hi {
width: 525px;
height: 263px;
background-position-x: "-7875px"
}
<button onclick="lockAnimation()">Click Me I'm Irish!</button>
<div id="hi"></div>
Change setInterval to setTimeout. This will run the function only once instead of running it every 100 ms.
var position_X = ["0px", "-525px", "-1050px", "-1575px", "-2100px", "-2625px", "-3150px", "-3675px", "-4200px", "-4725px", "-5250px", "-5775px", "-6300px", "-6825px", "-7350px"];
var _lock = document.getElementById('hi');
// console.log(_lock);
_lock.style.border = "1px solid black";
_lock.style.backgroundImage = "url('http://handbagmanufacturing.com/wp-content/CDN/images/lock.png')";
function lockAnimation(){
setTimeout(function(){
var _count = position_X.length;
for(var i = 0; i < _count; i++){
if(i == _count) break;
_lock.style.backgroundPosition = position_X[i] + " 263px";
console.log("Here is the background positions : " + i + ") " + position_X[i]);
}
}
, 100);
}
#hi {
width: 525px;
height: 263px;
background-position-x: "-7875px"
}
<button onclick="lockAnimation()">Click Me I'm Irish!</button>
<div id="hi"></div>

Storing an inline style into jquery variables

I have the following img tag,
<img id="image1" src="URL" alt="image1" name="image1" width="137" height="119" border="0" style="position: relative; left: -355px; top: 62px;" >
I would like to somehow, onclick, store the following items into seperate variables..
style="position: relative; left: -355px; top: 62px;"
var left = -355px
var top = 62px
Is that possible? Thank you!
Of course this is possible, have you tried something like this:
$('#image1').on('click', function () {
var style = 'style="' + $(this).attr('style') + '"';
var left = $(this).css('left');
var top = $(this).css('top');
alert(style);
alert(left);
alert(top);
});
Example: http://jsfiddle.net/9ZXHX/
var imageInfo = {style:null, left:null, top:null};
$('#image1').on('click', function() {
var $this = $(this);
imageInfo.style = $this.attr('style');
imageInfo.left = $this.css('left');
imageInfo.top = $this.css('top');
console.log('Image Clicked: ', imageInfo);
});
You could get the image with jquery, and then access its attributes from there.
var img = $("#image1");
var imgStyle = img[0].getAttribute("style");
var imgLeft = img.css("left");
var imgRight = img.css("right");
link to jquery's api for css: http://api.jquery.com/css/
In a function:
function getDetails(imgId)
{
var imgDetails = {};
var img = $("#"+imgId);
imgDetails.imgStyle = img[0].getAttribute("style");
imgDetails.imgLeft = img.css("left");
imgDetails.imgRight = img.css("right");
return imgDetails;
}
Here is a fiddle showing an example of this working, and the requested output in the question: http://jsfiddle.net/j7eYf/1/
I suggest your use jquery, it will make the job a lot easier. Try out this example,
$("#your trigger").live('click',function ()
{
$("#image1").css({
position: "absolute",
top: 62 + "px",
left: -355 + "px"
});
});

Cycling between 3 images (mobile Safari)

I have the following javascript. It works well when I am cycling between 2 images, but when I add a third it does not work correctly.
Here is my CSS:
img {
-webkit-transition-property: opacity;
-webkit-transition-duration: 2s;
position: absolute;
width: 320px;
height: auto;
}
img.fade-out {
opacity: 0;
}
img.fade-in {
opacity: 1;
}
Here is my javascript, which seems to work but seems laggy and definately not an elegant solution.
</head><body style="color: black">
<img id="one" class="fade-out" src="Wallpaper.png"/>
<img id="two" class="fade-out" src="Wallpaper0.png"/>
<img id="three" class="fade-out" src="Wallpaper1.png"/>
<script>
var images = ['Wallpaper.png', 'Wallpaper0.png', 'Wallpaper1.png'];
var index = 0;
var fade_in = one;
var fade_out = two;
var fade_foo = three;
fade_in.src = images[0];
fade_out.src = images[images.length - 1];
var fade = function () {
fade_in.src = images[index];
index = (index + 1) % images.length;
fade_in.className = 'fade-out';
fade_out.className = 'fade-in';
fade_foo.className = 'fade-out';
var fade_tmp = fade_in;
fade_in = fade_out;
fade_out = fade_foo;
fade_foo = fade_tmp;
setTimeout(fade, 15000);
};
fade();
</body></html>
For one thing, you're not changing fade_out.src. Try something like this:
fade_in.src = images[0];
fade_out.src = images[1]; // let's use image next to current for fade-out
var fade = function () {
fade_in.src = images[index];
index = (index + 1) % images.length;
fade_out.src = images[index]; // put next to current image into fade-out
// Code below does something misterious.
// You first switch classes between two img's, then switch variables themselves
// Why?
//fade_in.className = 'fade-out';
//fade_out.className = 'fade-in';
//var fade_tmp = fade_in;
//fade_in = fade_out;
//fade_out = fade_tmp;
setTimeout(fade, 15000);
};
Can't tell more since I don't know what exactly you're doing.
It seems you're only displaying one image at a time, so you don't need two variables, one will do. You just need to fade out the current image and bring in a new image:
var index = -1, count = /* total number of images */;
var image = null;
function fade() {
if (image != null)
image.className = 'fade-out';
index = (index + 1) % count;
image = document.getElementById('image-' + index);
image.className = 'fade-in';
setTimeout(fade, 15000);
}
fade();
This assumes that you have set up all the images in HTML as follows:
<img id="image-0" class="fade-out" src="..." />
<img id="image-1" class="fade-out" src="..." />
<img id="image-2" class="fade-out" src="..." />
...
Note that you can achieve cross-fading only if you have several images preloaded, as in the above example. If you use only one image and change the source, the previous image will be lost when you try to fade in the new one.
you're not waiting for you transitions to finish before you swap the source. we just need to rearrange the order of things.
var fade = function() {
fade_in.className = 'fade-out';
fade_out.className = 'fade-in';
setTimeout(function() {
index = (index + 1) % images.length;
fade_in.src = images[index]; // should be completely invisible at this time
var fade_tmp = fade_in;
fade_in = fade_out;
fade_out = fade_tmp;
}, 2000); // 2 seconds, same as your transition time
setTimeout(fade, 15000);
};
setTimeout(fade, 15000);
here the only work that the fade method does is to change the classes, which initiates the transitions. we set a delay that matches your transition time to update the index and swap the image source.
edits: i guess i'm not making it clear what's going on and the assumptions i'm making. here's my complete html except for the provided css which is the same. i also fixed an issue with image order since the last example.
<body>
<img id="one" class="fade-out" /><img id="two" class="fade-out" />
<script>
var images = ['16jog8h.jpg', '20_11_2007_0044537001195507712_joe_baran.jpg', '400davesrig.jpg'];
var index = 0;
var fade_in = document.getElementById('one');
var fade_out = document.getElementById('two');
// fade_in.src = images[0];
fade_out.src = images[0];
var fade = function() {
fade_in.className = 'fade-out';
fade_out.className = 'fade-in';
setTimeout(function() {
index = (index + 1) % images.length;
fade_in.src = images[index];
var fade_tmp = fade_in;
fade_in = fade_out;
fade_out = fade_tmp;
}, 2000);
setTimeout(fade, 5000);
};
fade();
</script>
</body>

Categories