I am working to make a slider that moves continuously while the users mouse is positioned over the arrow. It works but it keeps moving even when the content has ended.
How can I make it stop so that the forward/back motion is disabled once all the slides have been viewed, or so that they can't go backwards when they are viewing the first slide?
My code is below - open to other methods to achieve this type of slider if what I have is bad.
$(document).ready(function() {
var timer;
$("#leftarrow").hover(function() {
timer = setInterval(function() {slideLeft();}, 50);
}, function() {
clearInterval(timer);
});
$("#rightarrow").hover(function() {
timer = setInterval(function() {slideRight();}, 50);
}, function() {
clearInterval(timer);
});
function slideLeft() {
$("img#background").stop().animate({
'left': '-=200px'
}, 50);
$(".mid").stop().animate({
'left': '-=20px'
}, 50);
console.log('alert');
}
function slideRight() {
$("img#background").stop().animate({
'left': '-=200px'
}, 50);
$(".mid").stop().animate({
'left': '+=20px'
}, 50);
}
});
Here is a fiddle with my slider: http://jsfiddle.net/rYYDv/
You can use an additional if:
For slide left:
if(($(".mid").position().left) >= -500){ .. }
For slide right:
if(($(".mid").position().left) <= -10){ .. }
Disadvantage: You have to take care of the correct values manually. Which is not a problem, if the pictures don't change very often.
You should probably also add an additional else to ensure a correct final position (for the animate left property). But i think you get the idea.
http://jsfiddle.net/rYYDv/2/
I do not have enough points to comment on this post; hence, I'm writing it down here -
Similar post: How to make the Animate jQuery method stop at end of div?
Related
I have 2 static (html position: fixed;) images at the edges of the screen (right and left). When users scrolls more than 100 pixels from top, these edges retract 50 pixels.
I want to them to reappear (normal again, as they were at the beginning) when users scrolls back to top. I tried adding boolean value which is true when they retract and added it to condition when they need to reappear again. But it isn't working. Why?
userHasScrolled = false;
$(document).ready(function(){
$(window).scroll(function(){
if ($(window).scrollTop() > 100) {
$(".rightstatic").animate({marginRight:'-50px'}, 900);
$(".leftstatic").animate({marginLeft:'-50px'}, 900);
userHasScrolled = true;
}
});
});
if($(window).scrollTop() <= 0 && userHasScrolled) {
$(".rightstatic").animate({marginRight: '+50px'}, 400);
$(".leftstatic").animate({marginLeft:'+50px'}, 400);
userHasScrolled = false;
}
Edit:
$(document).ready(function(){
$(window).scroll(function(){
if ($(window).scrollTop() > 100) {
$(".rightstatic").animate({marginRight:'-20px'}, 900);
$(".leftstatic").animate({marginLeft:'-20px'}, 900);
} else if($(window).scrollTop() <= 0) {
$(".rightstatic").animate({marginRight: '+0px'}, 400);
$(".leftstatic").animate({marginLeft:'+0px'}, 400);
}
});
});
It kinda works, but has a HUGE delay. Like more than a minute after reaching top it retracts back.
Edit 2: After throttling it finally works. Thanks #TomaszBubała.
It isn't working because the bottom part of your code is called only once and userHasScrolled is false by that time. You need to combine both inside $(window).scroll(). I think you can get rid of userHasScrolled variable and second condition could be just else instead of else if.
var scrollTimeout;
var throttle = 250;
$(document).ready(function(){
$(window).scroll(function(){
if(scrollTimeout) return;
scrollTimeout = setTimeout(function() {
scrollTimeout = null;
const scrolled = $(this).scrollTop();
if (scrolled > 100) {
console.log("1");
$(".rightstatic").animate({marginRight:'-20px'}, 900);
$(".leftstatic").animate({marginLeft:'-20px'}, 900);
} else {
console.log("2");
$(".rightstatic").animate({marginRight: '+0px'}, 400);
$(".leftstatic").animate({marginLeft:'+0px'}, 400);
}
}, throttle);
});
});
Fiddle: https://jsfiddle.net/wctxbynt/41/
EDIT:
It wasn't working as intended since scroll event is fired multiple times (tens of times) with a single mousewheel interaction, causing jQuery animate to be called far too many times than it needs to be. A common way to fix this problem is to "throttle" a function not to be called unless a certain amount of time has passed. In edited code above we define timeout as 250ms, which means that our scroll handler code will get called up to 4 times a second - not more (a big difference as opposed to ex. 30 times in 100ms which is huge improvement in performance). Above is just an easy implementation of throttle function - read more about throttling here.
I have an image embedded in a container with a background image to give the effect of scrolling within the page. Initially, I had the scrolling effect take place on page load, with this simple bit of script which worked perfectly.
$(window).on("load", function () {
$(".embedded_scroller_image").animate({ scrollTop: $('.embedded_scroller_image')[0].scrollHeight}, 2500, "easeInOutCubic");
}); // end on load
However, the element is too far down the page now and I want that animation to fire when the element enters 80% of the viewport. That part is also working fine with this code here (I'm using a scroll limiter to improve browser performance)
// limit scroll call for performance
var scrollHandling = {
allow: true,
reallow: function() {
scrollHandling.allow = true;
},
delay: 500 //(milliseconds) adjust to the highest acceptable value
};
$(window).on('scroll', function() {
var flag = true;
if(scrollHandling.allow) { // call scroll limit
var inViewport = $(window).height()*0.8; // get 80% of viewport
$('.embedded_scroller_image').each(function() { // check each embedded scroller
var distance = $(this).offset().top - inViewport; // check when it reaches offset
if ($(window).scrollTop() >= distance && flag === true ) {
$(this).animate({ scrollTop: $(this)[0].scrollHeight}, 2500, "easeInOutCubic"); //animate embedded scroller
flag = false;
}
});
} // end scroll limit
}); // end window scroll function
The problem is this: I want the autoscroll to happen once and then stop. Right now, it works on entering viewport, but if I then try to manually scroll the image, it keeps pushing back down or stutters. You can't get the element to scroll normally. I attempted to use the flag in the code to stop the animation, but couldn't get that to successfully work.
How can I have this animation fire when the element is 80% in the viewport, but then completely stop after one time?
Here is a codepen I mocked up as well http://codepen.io/jphogan/pen/PPQwZL?editors=001 If you scroll down, you will see the image element autoscroll when it enters the viewport, but if you try to then scroll that image up in its container, it won't work.
Thanks!
I have tweaked your script a bit:
// limit scroll call for performance
var scrollHandling = {
allow: true,
reallow: function() { scrollHandling.allow = true; },
delay: 500 //(milliseconds) adjust to the highest acceptable value
};
$(window).on('scroll', function() {
if(scrollHandling.allow) { // call scroll limit
var inViewport = $(window).height()*0.8; // get 80% of viewport
$('.embedded_scroller_image').each(function() { // check each embedded scroller
var distance = $(this).offset().top - inViewport; // check when it reaches offset
if ($(window).scrollTop() >= distance ) {
$(this).animate({ scrollTop: $(this)[0].scrollHeight}, 2500, "easeInOutCubic"); //animate embedded scroller
scrollHandling.allow = false;
}
});
} // end scroll limit
}); // end window scroll function
I have kicked out your flag and simply made use of scrollHandling.allow declared already.
Try if it works for you :)
Cheers!
I'm trying to figure out why this script is not working.
What I have is a div hiding behind another div and need it to animate up after a user scrolls on the page.
This is my script:
$(document).scroll(function(){
var top = $(document).scrollTop();
if (top > 50) {
$('#merch').animate({ bottom: 200 },
{duration: 1000, easing: 'easeOutBounce'});
}
else {
$('#merch').slideDown();
}
});
$(document).scroll(function(){
var top = $(document).scrollTop();
if (top > 50) {
$('#merch').animate({ top: '500px' },
{duration: 1000});
}
else {
$('#merch').slideDown();
} });
I'm getting an error that on the easing value you are passing, might want to look into that.
animate values need to be in quotes with a px value
make sure merch has 'position: relative;' in the CSS. without it, the jQuery can't move the element
There is no onscrollcomplete function, but you can monkey wrench one together:
var int;
$(window).scroll(function(){
clearTimeout(int);
int = setTimeout(function(){
//animation here
}, 300);
});
Wait 300ms then fire the animation function to pull the div to the top of the page.
I am working on a project where I am assigned a task to make a blink image moving on the web page from the left to the right.
The image should move(step up) and blink each second.
I know how to make it blink, my code is below:
function blink(time, interval){
var timer = window.setInterval(function(){
$("#img").css("opacity", "0.1");
window.setTimeout(function(){
$("#img").css("opacity", "1");
}, 100);
}, interval);
window.setTimeout(function(){clearInterval(timer);}, time);
}
blink(5000, 1000);
But I don't know how to move it on a second basis and at the same time blink it.
Please, help me guys!
Thanks
how about using jquery animate?
$("#img").animate({marginLeft:'500px'},1000);
Here's a demo that is using only the power of the animate function :
http://jsfiddle.net/vtZd5/
try this:
function blink() {
$('div').fadeTo(1000, 0.1, function(){
$(this).animate({opacity: '1', top: '+=20px'}, 500);
blink()
})
}
blink()
http://jsfiddle.net/AJSk3/3/
I have a #ball that when clicked uses jquery animate to move down 210px using this code:
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, 500);
setTimeout(crack, 400);
});
currently Im using Timeout to trigger the next function which is "crack".
Instead I want to track the movement of #ball and when its css top = 210px I want to trigger the function crack(), how can I do this?
I saw in a somewhat similar post that the Step function might be what I'm looking for, but I am not sure how to approach that solution based on the info provided at http://api.jquery.com/animate/
Look at Demo: http://jsfiddle.net/EnigmaMaster/hbvev/4/
I am not sure why you want to use a tracker if you know that the ball will reach the box in 210px.
If you want to get rid of setTimeout, then use the .animate callback function which will be called when the ball reaches the box.
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, 500, crack); //<== crack will be called after ball animation
});
DEMO
Incase if you want to call crack when the ball touches the box and still continue the movement of box then you can execute it 2 steps like below,
$('#ball').click(function() {
$(this).animate({
top: '+=180px'
}, 400, function() {
crack();
$(this).animate({
top: '+=30px'
}, 100);
});
});
Also check this version for fun in slow motion http://jsfiddle.net/skram/hbvev/8/
If you truly want to do something based on the position of the ball, then yes, step is probably the best way to go:
$('#ball').click(function() {
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function() {
if($(this).offset().top > 208) {
crack();
}
}
});
});
Demo: http://jsfiddle.net/qJjnN/1/
Now, there are a couple of caveats:
There will be a possible performance hit.
The position at each step will not necessarily be a whole number, and the object will not exist at every pixel between the start and stop location.
step is not called on the final position, so you cannot actually check for 210 if it is the final location.
Taking those into mind, you will not be able to check for the exact position of 210px. Instead, you will want to watch when it passes a certain position and only trigger crack at that point and not every point after:
$('#ball').click(function() {
var cracked = false;
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function() {
if($(this).offset().top > 208 && !cracked) {
cracked = true;
crack();
}
}
});
});
Demo: http://jsfiddle.net/qJjnN/2/
The step function also has parameters now and fx that can be used to see the current value of the css being animated. step is called for each step of each css attribute being animated. So, you have to be careful using those, because you need to look at fx to see what attribute value you are looking at (if you are animating more than one, i.e. top and left).
$('#ball').click(function() {
var cracked = false;
$(this).animate({
top: '+=210px'
}, {
duration: 500,
step: function(now, fx) {
if(fx.prop != 'top') {
return;
}
if(now > 208 && !cracked) {
cracked = true;
crack();
}
}
});
});