JQuery continuous image carousel only moving one image at a time? - javascript

Currently working on an image carousel and I believe it is 99% done, except for one thing... I can only move one picture at a time, and then I have to rehover in order to keep the slider going. So is there some sort of jump statement or goto statement that I can use to continually run the loops?
Here is what I have so far :
Fiddle
JQuery
$(document).ready(function(){
$('.carousel').each(function(){
if($(this).width() < $(this).children('ul').width()){
$(this).children('carrow').each(function(){
$(this).hide();
});
}
});
$('.carousel').hover(function(){
$(this).children('.carrow').each(function(){
$(this).addClass('carrow-hover');
});
}, function(){
$(this).children('.carrow').each(function(){
$(this).removeClass('carrow-hover');
});
});
$('.carrow').hover(function(){
var SD = 210;
var $carousel = $(this).parent();
var $ul = $carousel.children('ul');
var distance = SD;
var time = 2500;
var rate = distance/time;
//When animation is completed, Jump back to here
distance = Math.abs($ul.position().left);
if($(this).hasClass('left-arrow')){
if(distance == 0) {
$ul.css({left: -210});
$ul.prepend($ul.children('li:last-child'));
} else {
time = distance/rate;
}
$ul.stop().animate({
left: 0
}, time, 'linear');
}
else if($(this).hasClass('right-arrow')){
if(distance != 0){
distance = SD - distance;
time = distance/rate;
}
$ul.stop().animate({
left: -210
}, time, 'linear', function(){
$ul.append($ul.children('li:first-child'));
$ul.css({left: 0});
});
}
}, function(){
$(this).parent().children('ul').stop();
});
});

You can separate animation routine in it's own function, e.g.
function myAnimate(that){
// animation goes here
}
And call itself as a callback function at the animation end
$ul.stop().animate({
left: 0
}, time, 'linear', function(){myAnimate(that)});
This way as soon as one animation ends - the other begins
Demo: http://jsfiddle.net/bjyuA/1/

All I did was loop the part I had wanted and created a few extra dependencies which Yuriy had fixed, but I figured I would share my approach as well.
$('.carrow').hover(function(){
var SD = 210;
var $this = $(this);
var $carousel = $(this).parent();
var $ul = $carousel.children('ul');
var distance = SD;
var time = 2500;
var rate = distance/time;
distance = Math.abs($ul.position().left);
continue_scroll = function(dist) {
time = 2500;
if(arguments.length != 0){
distance = dist;
}
if($this.hasClass('left-arrow')){
if(distance == 0) {
time = 2500;
} else {
time = distance/rate;
}
$ul.stop().animate({
left: 0
}, time, 'linear', function(){
$ul.prepend($ul.children('li:last-child'));
$ul.css({left: -210});
continue_scroll(210);
});
}
else if($this.hasClass('right-arrow')){
if(distance != 0 && arguments.length == 0){
distance = SD - distance;
time = distance/rate;
}
$ul.stop().animate({
left: -210
}, time, 'linear', function(){
$ul.append($ul.children('li:first-child'));
$ul.css({left: 0});
continue_scroll(0);
});
}
}
continue_scroll();
}, function(){
$(this).parent().children('ul').stop();
});

Related

Get elements coordinates

I need some help here.
First off, here is a small demo code from my game: https://jsfiddle.net/MiloSx7/a0dn9a4f/2/
Animation idea: Make the coin scale to 2x after it's collected, then slowly move it and gradually reduce scale to the exact spot where the image displaying the coin inventory stat is , invLocation is the ID of the element where the animation should end. It starts from the current coinId X and Y
Is it possible to somehow get the X and Y of the invLocation, so that I know where should I tell the animation to move?
You can do this with JQuery position() and offset() methods.
const spawnTime = 10000;
var coin = 0;
var intervalId = '';
var coinDiv = $('#coinDiv');
var coinImg = $('#coinImg');
var invDiv = $('#invDiv');
var invId = $('#inventoryId');
var invImg = $('#invLocation');
coinImg.on('click', collect);
intervalId = setInterval(setLocation, spawnTime);
function setLocation() {
var x = parseInt( Math.random()*(80-20+1) ) + 20;
var y = parseInt( Math.random()*(80-20+1) ) + 20;
coinImg.animate({
opacity: 1
}, 3000,
function() {
coinImg.css('top', x+'%');
coinImg.css('left', y+'%');
coinImg.css('display', 'initial');
setTimeout( () => coinImg.animate({ opacity: 0 }, 3000), 6000);
});
}
function collect() {
clearInterval(intervalId);
coinImg.stop();
coinImg.css('opacity', 1);
/* Increment coin counter */
coin++;
invId.text(coin);
/* In order to disable multiple clicks */
coinImg.css('pointer-events', 'none');
/* Double the size */
coinImg.css('width', '128px');
coinImg.css('height', '128px');
/* Animate and return to normal */
coinImg.animate({
width: '32px',
height: '32px',
left: invImg.offset().left + 'px',
top: invImg.offset().top + 'px'
}, 1500,
function() {
coinImg.css('pointer-events', 'auto');
coinImg.css('display', 'none');
coinImg.css('width', '64px');
coinImg.css('height', '64px');
intervalId = setInterval(setLocation, spawnTime);
}
);
}
Working example: https://jsfiddle.net/wz4q9w69/

Slow Scroll jittery

I am using this code: EXAMPLE
Depending on if "image-ul" is fully above the bottom edge of the browser window or not, will make divs scroll at different speeds, as it should. But the problem that I am having is that the scrolling is not smooth when the slow scrolling divs get somewhere close to the top of the page. They seem to stall for a moment, and even scroll in the opposite direction sometimes.
//
// default speed ist the lowest valid scroll speed.
//
var default_speed = 1;
//
// speed increments defines the increase/decrease of the acceleration
// between current scroll speed and data-scroll-speed
//
var speed_increment = 0.01;
//
// maximum scroll speed of the elements
//
var data_scroll_speed_a = 3; // #sloganenglish
var data_scroll_speed_b = 5; // #image-ul
//
//
//
var increase_speed, decrease_speed, target_speed, current_speed, speed_increments;
$(document).ready(function() {
$(window).on('load resize scroll', function() {
var WindowScrollTop = $(this).scrollTop(),
Div_one_top = $('#image-ul').offset().top,
Div_one_height = $('#image-ul').outerHeight(true),
Window_height = $(this).outerHeight(true);
if (WindowScrollTop + Window_height >= (Div_one_top + Div_one_height)) {
$('#sloganenglish').attr('data-scroll-speed', data_scroll_speed_a).attr('data-current-scroll-speed', default_speed).attr('data-speed-increments', data_scroll_speed_a * speed_increment);
$('#image-ul').attr('data-scroll-speed', data_scroll_speed_b).attr('data-current-scroll-speed', default_speed).attr('data-speed-increments', data_scroll_speed_b * speed_increment);
$('.slogan-a-line').css('color', 'yellow');
increase_speed = true;
decrease_speed = false;
} else {
$('#sloganenglish').attr('data-scroll-speed', '1').attr('data-current-scroll-speed', default_speed);
$('#image-ul').attr('data-scroll-speed', '1').attr('data-current-scroll-speed', default_speed);
$('.slogan-a-line').css('color', 'red');
decrease_speed = true;
increase_speed = false;
}
}).scroll();
});
// data-scroll-speed script
$.fn.moveIt = function() {
var $window = $(window);
var instances = [];
$(this).each(function() {
instances.push(new moveItItem($(this)));
});
window.onscroll = function() {
var scrollTop = $window.scrollTop();
instances.forEach(function(inst) {
inst.update(scrollTop);
});
}
}
var moveItItem = function(el) {
this.el = $(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
this.current_speed = 1.0;
};
moveItItem.prototype.update = function(scrollTop) {
target_speed = parseInt(this.el.attr('data-scroll-speed'));
current_speed = this.current_speed;
speed_increments = parseFloat(this.el.attr('data-speed-increments'));
if (increase_speed) {
if (current_speed < target_speed) {
current_speed += speed_increments;
} else {
current_speed = target_speed;
}
} else if (decrease_speed) {
if (current_speed > default_speed) {
current_speed -= speed_increments;
}
if ($(window).scrollTop() === 0) {
current_speed = default_speed;
}
}
this.current_speed = current_speed;
var pos = scrollTop / this.current_speed;
this.el.css('transform', 'translateY(' + -pos + 'px)');
};
// Initialization
$(function() {
$('[data-scroll-speed]').moveIt();
});
The sample code wasn't slow for me, so it may be specific to your machine or browser.
However, there are a few things you can do:
Don't use jQuery where you don't need it. jQuery is significantly slower than using native JS functions (e.g. document.getElementById).
Don't repeatedly use jQuery selectors. Every time you use a jQuery selector, you suffer a performance hit. So for example, instead of this:
function(){
var Div_one_top = $('#image-ul').offset().top,
Div_one_height = $('#image-ul').outerHeight(true);
}
Do this:
var imageUl = $('#image-ul');
function(){
imageUl.offset().top,
imageUl.outerHeight(true);
}
This example should increase performance quite a bit. You're doing multiple jQuery selectors every time the page scrolls for no reason.
The best choice for something performance intensive is to cut out jQuery completely and do it by hand.

jQuery animate() doesn't correctly animate height the second time

I have built a toggle that will slide down a div to reveal content. I am not using the normal toggle() function of jQuery because I wanted to show the top 300px of content and then slide to reveal the rest.
Anyways, I have a script setup that animates the height of the container div, which reveals the content inside.
function slideCut() {
var revertHeight = 300;
var finalHeight = 0;
var s = 1000;
$('.cutBottom a').click(function() {
event.stopPropagation();
var p = $(this).parent().parent();
var h = p.css('height', 'auto').height();
var cut = $(this).parent().find('.cutRepeat');
// Fix height
if (finalHeight == 0) {
p.css('height', 'auto');
finalHeight = p.height();
p.height(revertHeight);
}
if ($(this).hasClass('toggled')) {
$(this).removeClass('toggled');
p.animate({height:revertHeight}, {
duration: s
});
cut.fadeIn('fast');
} else {
$(this).addClass('toggled');
p.animate({height:finalHeight}, {
duration: s,
complete: function() {
cut.fadeOut('fast');
}
});
}
return false;
});
}//end
The problem is, the second time it animates the height to the full size (sliding the div to reveal content) it does not animate, it just jumps to the full height. Why is this happening?
Working example: http://jsfiddle.net/6xp2Y/3/
After all that hard work and fiddle being broken, all we had to do was remove one line from your code:
function slideCut() {
var revertHeight = 300;
var finalHeight = 0;
var s = 1000;
$('.cutBottom a').click(function() {
event.stopPropagation();
var p = $(this).parent().parent();
//var h = p.css('height', 'auto').height(); //REMOVE THIS LINE
var cut = $(this).parent().find('.cutRepeat');
// Fix height
if (finalHeight == 0) {
p.css('height', 'auto');
finalHeight = p.height();
p.height(revertHeight);
}
if ($(this).hasClass('toggled')) {
$(this).removeClass('toggled');
p.animate({height:revertHeight}, {
duration: s
});
cut.fadeIn('fast');
} else {
$(this).addClass('toggled');
p.animate({height:finalHeight}, {
duration: s,
complete: function() {
cut.fadeOut('fast');
}
});
}
return false;
});
}//end
slideCut();
Updated your fiddle: http://jsfiddle.net/brandonscript/6xp2Y/5/
Updated answer!
The proplem lies here
if (finalHeight == 0) {
parent.css('height', 'auto');
finalHeight = parent.height();
parent.height(revertHeight);
console.log('finalHeight:'+finalHeight);
}
This is only running at the beginning, because finalHeight is not 0 anymore after first run.
You can fix this by setting finalHeight back to 0 after closing it again, like so
if ($(this).hasClass('toggled')) {
$(this).removeClass('toggled');
parent.animate({height:revertHeight}, {
duration: speed
});
cut.fadeIn('fast');
finalHeight = 0;
} else { [...]

How can I make a div appear over specific area tags on an image on mouseover?

I have some javascript that moves an image continuously left. When you mouseover the image, I want the scrolling to stop, and I want a slightly transparent div with some custom text to appear over whatever area tag your mouse is over.
Here is the JS I'm using, and I commented out where things should happen. How would I do this?
$(document).ready(function() {
var date = new Date();
var style = "day"
if (date.getHours() >= 17 && date.getHours() <=5) {
style="night";
}
setInterval(wells_fancy_slider, 50);
$('area').hover(function() {
// here is where the code should go
paused = true;
}, function() {
// here is where you hide the div
paused = false;
})
})
function wells_fancy_slider() {
if (!paused) {
if (parseInt($('#pic1').css('left')) < -2770) {
$('#pic1').css('left', '5586');
}
if (parseInt($('#pic2').css('left')) < -2770) {
$('#pic2').css('left', '5586');
}
if (parseInt($('#pic3').css('left')) < -2770) {
$('#pic3').css('left', '5586');
}
$('#pic1, #pic2, #pic3').css('left', '-=5');
}
}
Not sure it will fit your needs:
CSS:
#mydiv{position:absolute;display:none}
$('area').hover(function() {
$('mydiv').offset({ top: $(this).offset().top, left: $(this).offset().left}).fadeIn();
paused = true;
}, function() {
$('#mydiv').hide();
paused = false;
})
Try this one..
t = setInterval(wells_fancy_slider, 50);
$('#area').hover(function(e) {
clearInterval(t);
var parentOffset = $(this).offset(); // or $(this).parent().offset();
var x = e.pageX - parentOffset.left;
var y = e.pageY - parentOffset.top;
paused = true;
}, function() {
clearInterval(t);
t = setInterval(wells_fancy_slider, 50);
paused = false;
});

Why does smooth scrollBy only work first time?

I am using the following code on a website to imitate smooth scrolling:
function scrollWindow() {
// window.scrollBy(1040,0)
var timerID = setInterval(function() {
window.scrollBy(104, 0);
if( window.pageXOffset >= 1040 ) clearInterval(timerID);
}, 10);
}
However, after clicking Scroll (the scrollWindow function) the page scrolls 1040 like it should.
Any subsequent time, it does not work, unless i manually scroll back to the beginning.
Would i be right in thinking that if( window.pageXOffset >= 1040 ) is canceling it because although it hasn't moved 1040, it is past that point on the page?
If so, how can i solve this?
Yes, your assessment is correct; but it could be corrected with a twist in the approach:
function scrollWindow() {
var scrolledSoFar = 0;
var scrollStep = 104;
var scrollEnd = 1040;
var timerID = setInterval(function() {
window.scrollBy(scrollStep, 0);
scrolledSoFar += scrollStep;
if( scrolledSoFar >= scrollEnd ) clearInterval(timerID);
}, 10);
}
Update
Another pitfall in the code is that you are executing scrollBy before checking for the condition. So on your page, even after you have scrolled past 1040, clicking scroll will move the page by one scrollStep amount. To prevent that, this order is better:
function scrollWindow() {
var scrolledSoFar = 0;
var scrollStep = 104;
var scrollEnd = 1040;
var timerID = setInterval(function() {
if( scrolledSoFar < scrollEnd ) {
window.scrollBy(scrollStep, 0);
scrolledSoFar += scrollStep;
} else {
clearInterval(timerID);
}
}, 10);
}

Categories