I have a div "box" which fades gradually using ".fp-viewing" as an anchor to start the transition effect when a user scrolls to the next page. The thing is the page starts scrolling when .fp-viewing is triggered and scrolls box out of view before the finish of the animation.
How can I delay the start of the scrolling when .fp-viewing is triggered till box has done its animation in 4s?
.box{
transition: all 4s ease-out;
-webkit-transition: all 4s ease-out;
}
.fp-viewing-2 .box{
opacity: 0;
}
You can play with the option fullpage.js provides to cancel a movement before it takes place.
Reproduction online
var delay = 2000; //milliseconds
var timeoutId;
var animationIsFinished = false;
new fullpage('#fullpage', {
sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
onLeave: function(origin, destination, direction){
var curTime = new Date().getTime();
//animating my element
$('#element').addClass('animate');
clearTimeout(timeoutId);
timeoutId = setTimeout(function(){
animationIsFinished = true;
fullpage_api.moveTo(destination.index + 1);
}, delay);
return animationIsFinished;
},
});
#fullpage {
transition-delay: 1s !important;
}
or modify function addAnimation
in fullpage.js
for me work this variant:
$(elem).fullpage({
/// opttions,
onLeave: function(origin, destination, direction){
if(animationIsFinished === false){
// do some code
}
clearTimeout(timeoutId);
timeoutId = setTimeout(function(){
animationIsFinished = true;
$.fn.fullpage.moveTo(destination);
setTimeout(() => {
animationIsFinished = false;
}, 200);
}, 600);
return animationIsFinished;
This is cheap and easy, but I just wrap the Full Page function I need in custom function wrapper, then use settimeout (a la this answer) to fire it when I'm ready.
function slideWithDelay() {
fullpage_api.moveSlideRight();
}
// Change slide on select
$('select').on('change',function(){
setTimeout(slideWithDelay, 500);
})
Related
I have a div "box" which fades gradually using ".fp-viewing" as an anchor to start the transition effect when a user scrolls to the next page. The thing is the page starts scrolling when .fp-viewing is triggered and scrolls box out of view before the finish of the animation.
How can I delay the start of the scrolling when .fp-viewing is triggered till box has done its animation in 4s?
.box{
transition: all 4s ease-out;
-webkit-transition: all 4s ease-out;
}
.fp-viewing-2 .box{
opacity: 0;
}
You can play with the option fullpage.js provides to cancel a movement before it takes place.
Reproduction online
var delay = 2000; //milliseconds
var timeoutId;
var animationIsFinished = false;
new fullpage('#fullpage', {
sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
onLeave: function(origin, destination, direction){
var curTime = new Date().getTime();
//animating my element
$('#element').addClass('animate');
clearTimeout(timeoutId);
timeoutId = setTimeout(function(){
animationIsFinished = true;
fullpage_api.moveTo(destination.index + 1);
}, delay);
return animationIsFinished;
},
});
#fullpage {
transition-delay: 1s !important;
}
or modify function addAnimation
in fullpage.js
for me work this variant:
$(elem).fullpage({
/// opttions,
onLeave: function(origin, destination, direction){
if(animationIsFinished === false){
// do some code
}
clearTimeout(timeoutId);
timeoutId = setTimeout(function(){
animationIsFinished = true;
$.fn.fullpage.moveTo(destination);
setTimeout(() => {
animationIsFinished = false;
}, 200);
}, 600);
return animationIsFinished;
This is cheap and easy, but I just wrap the Full Page function I need in custom function wrapper, then use settimeout (a la this answer) to fire it when I'm ready.
function slideWithDelay() {
fullpage_api.moveSlideRight();
}
// Change slide on select
$('select').on('change',function(){
setTimeout(slideWithDelay, 500);
})
The behavior I'm trying to achieve is this:
On hover/mouseenter, change the background image from the placeholder to a gif whose positions changes in order to achieve an animated effect, then go back to the placeholder when the mouse leaves.
My code is
$('.filmstrip').mouseenter(function(){
var $that = $(this),
w = $that.width(),
fr = $that.attr('data-framerate');
$that.css('background-image','url('+$that.attr('data-gifurl')+')');
for ( var i = 1, n = $that.attr('data-ticks'); i <= n; ++i )
{
(function(j){
setTimeout(function(){
$that.css('background-position-x','-'+(w*j)+'px');
}, j*fr);
})(i);
}
$that.bind('mouseleave',function(){
$that.css('background-image','url('+$that.attr('data-placeholder')+')').css('background-position-x','0');
});
});
and the bug I'm having is that if the gif hasn't finished animating, then the
.css('background-position-x','0')
part of
$that.css('background-image','url('+$that.attr('data-placeholder')+')').css('background-position-x','0');
});
doesn't work because the background position is still being moved by the animation. So I need some way to first stop the setTimeout stuff if it isn't finished running. Any idea how I can do that?
This may be something better done with CSS rather than javascript.
Option #1 - Use an actual GIF
You could compile the frames which you want animated into an actual GIF file, and then have the background image change based on hover:
<div class="filmstrip"></div>
And then CSS
.filmstrip { background:transparent url('static_image.jpg') no-repeat 0 0 }
.filmstrip:hover { background-image:url( 'animated_image.gif' ) }
Option #2 - Use CSS3 Animation
You could keep the animated image as a strip of frames (of a known length) and then use something like:
<div class="filmstrip"></div>
With CSS
.filmstrip { background:transparent url('static_image.jpg') no-repeat 0 0 }
#keyframes animate-bg {
0% { background-position: 0 0 }
100% { background-position: -1000px 0 }
/* where 1000px is the length of the strip */
}
.filmstrip:hover { animation: animate-bg 5s steps(50) infinite }
/* where 5s is the overall loop length time and 50 is the number of frames in the strip */
Option #3 - Use Spritely
Spritely is a jQuery plugin which seems to manage all elements of turning a filmstrip/sprite image into an animation, including being able to start/stop the animation, reset to the first frame, change FPS, etc.
Add a stop variable :
$('.filmstrip').mouseenter(function(){
var isStopped = false;
var $that = $(this),
w = $that.width(),
fr = $that.attr('data-framerate');
$that.css('background-image','url('+$that.attr('data-gifurl')+')');
for ( var i = 1, n = $that.attr('data-ticks'); i <= n && !isStopped; ++i )
{
(function(j){
setTimeout(function(){
if (!isStopped) {
$that.css('background-position-x','-'+(w*j)+'px');
}
}, j*fr);
})(i);
}
$that.bind('mouseleave',function(){
isStopped = true;
$that.css('background-image','url('+$that.attr('data-placeholder')+')').css('background-position-x','0');
});
});
If isStopped is not accessible (because not tested) from the timeout, then just create a new variable in a inner scope which you affect isStopped value.
You can use an interval based solution like
$('.filmstrip').mouseenter(function() {
var $that = $(this),
w = $that.width(),
fr = +$that.attr('data-framerate'),
ticks = +$that.attr('data-ticks');
$that.css('background-image', 'url(' + $that.attr('data-gifurl') + ')');
var counter = 0;
var interval = setInterval(function() {
$that.css('background-position-x', '-' + (w * ++counter) + 'px');
if (counter >= ticks) {
clearInterval(interval);
}
}, fr);
$(this).data('bg-interval', interval)
}).mouseleave(function() {
clearInterval($(this).data('bg-interval'));
$(this).css('background-image', 'url(' + $(this).attr('data-placeholder') + ')').css('background-position-x', '0');
});
.filmstrip {
height: 64px;
border: 1px solid grey;
background-position: right;
background-position-y: inherit;
display: inline-block;
width: 64px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="filmstrip" data-framerate="400" data-ticks="10" data-gifurl="//cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg?v=bc7c2f3904bf">
</div>
U can use clearTimeout to stop setTimeOut.
Working Demo-
var myVar;
function myFunction() {
myVar = setTimeout(function(){ alert("Hello"); }, 3000);
}
function myStopFunction() {
clearTimeout(myVar);
}
<p>Click the first button to alert "Hello" after waiting 3 seconds.</p>
<p>Click the second button to prevent the first function to execute. (You must click it before the 3 seconds are up.)</p>
<button onclick="myFunction()">Try it</button>
<button onclick="myStopFunction()">Stop the alert</button>
More-
Mozilla Developer Network
and
W3School
I am having a view problems with animating a background to give the impression that a window is opening, I have the animation actually animating but it just animates like the images are in sequence. What I am wanting is to give the impression of a movie or animated gif.
You can see my current attempt here,
http://jsfiddle.net/8nj4934w/
I have so far done the following javascript,
$('a').bind('mouseenter', function() {
var self = $(this);
this.iid = setInterval(function() {
self.animate({ 'background-position-y': '-=500px' });
}, 300);
}).bind('mouseleave', function(){
this.iid && clearInterval(this.iid);
});
and the kind of effect I am going for here,
http://www.jeld-wen.com/catalog/exterior-doors
just hover of a door image.
Update (for jQuery solution handling two way sliding)
function slide(that, increment, limit){
var self = $(that);
that.iid && clearInterval( that.iid );
that.pos = that.pos || 0;
return setInterval(function () {
that.pos = that.pos += increment;
if (that.pos === limit){
clearInterval(that.iid);
} else {
self.css({
'background-position': '0 '+ that.pos + 'px'
});
}
}, 50);
}
$('a').bind('mouseenter', function () {
this.iid = slide( this, -500, -11500 );
}).bind('mouseleave', function () {
this.iid = slide(this, 500, 0);
});
Demo at http://jsfiddle.net/g8cypadx/
Original answer
I would suggest that you use CSS transitions with steps.
a {
background-image: url('https://dl.dropboxusercontent.com/u/58586640/9100_FRONT_STRIP.png');
background-repeat: no-repeat;
height: 500px;
width: 500px;
display: block;
background-position: 0 0;
transition: background-position 1s steps(23);
}
a:hover {
background-position: 0 -11500px; /* number of steps times the height */
}
If you have to do it through jQuery then you should animate both properties but with 0 duration for the animation, and small delay for the interval
$('a').bind('mouseenter', function () {
var self = $(this);
this.iid = setInterval(function () {
self.animate({
'background-position': '-=0 -=500px'
}, 0);
}, 50);
}).bind('mouseleave', function () {
this.iid && clearInterval(this.iid);
});
Demo at http://jsfiddle.net/8nj4934w/2/
(the problem with this solution is that it will not stop at the end)
Suppose you have an animation running with a certain time like this:
$('span').animate({opacity : 1}, 10000);
The animation is quite long so the user tries clicking the button again. The animation will be a certain amount of time through the animation already, which is probably going to be different every time.
On the second click is it possible to update the animation process keeping the opacity of the object when the user clicks, just changing the time it will take to finish?
Basically I want to update the animation process mid way through the animation.
You can use the step option of animate to keep track of how far along the animation is. Then with that information, you can calculate the time remaining in the animation. Then stop the current animation and start a new one with half the duration.
http://jsfiddle.net/MdD45/
EDIT
It looks like the 2nd parameter passed to step contains a property named pos which tells you what percentage along in the animation you are. That can simplify things further.
http://jsfiddle.net/MdD45/1/
var startVal = 0;
var endVal = 1;
var duration = 10000;
var howfar = 0;
$('span').css("opacity",startVal)
.animate({
opacity : endVal
}, {
duration: duration,
step: function(now, fx){
howfar = fx.pos; // between 0 and 1, tells how far along %
}
});
$("button").click(function(){
// calculate the new duration as half of the remaining duration
var timeRemaining = duration - (howfar * duration);
duration = timeRemaining / 2;
$('span').stop().animate({
opacity : endVal
}, {
duration: duration,
step: function(now, fx){
howfar = fx.pos; // between 0 and 1, tells how far along %
}
});
});
I put something together yesterday to skip in jQuery animations, here's the code, it should be pretty easy to modify for your use-case:
EDIT: Modified version:
Demo: http://jsfiddle.net/SO_AMK/fJyKM/
jQuery:
var time = 10000;
var opacity = 1;
var currentTime = 0;
$("#square").animate({
opacity: opacity
}, {
duration: time,
step: function(now, fx) {
currentTime = Math.round((now * time) / opacity);
},
easing: "linear"
});
$("#hurry").click(function() {
$("#square").stop().animate({
opacity: opacity
}, {
duration: ((time - currentTime) / 4), // Get remaining time, divide by 4
step: function(now, fx) {
currentTime = Math.round((now * time) / opacity);
},
easing: "linear"
});
});
It also works for other properties, like width. The only catch is that if it is a decreasing value than you need to use a different script.
yes you can ..
You have to stop the animation with "stop()" method then start a new animation against the same node on the same property and as a target value, the original one.
I'm not fully sure if this would work, but consider doing like this:
<div id="box"></div>
<style type="text/css">
div#box {
-webkit-transition: width 10s;
-moz-transition: width 10s;
transition: width 10s;
background: #000;
width: 100px;
}
div#box.speedy {
-webkit-transition: width 5s;
-moz-transition: width 5s;
transition: width 5s;
}
</style>
<script style="text/javascript">
$(function() {
$('div#box').css('width', '400');
setTimeout(function() {
$('div#box').addClass('box');
}, 2000);
});
</script>
Basicly let css animate it, and add another class that speeds the transition up.
Consider we have a simple cycling Javascript process as:
function test() {
el=document.getElementById("test");
var opacity = 1;
var id = setInterval(function() {
opacity = opacity - 0.1;
el.style.opacity= opacity;
\\ if(mouseout) {clearInterval(id);} How to do this?
if(opacity == 0) {clearInterval(id);}
}, 500);
}
document.getElementById("test").
addEventListener('mouseover', function(){
test();
});
Upon moveover event, the process initiates and continues until reaching the if condition. How we can define another if condition to stop the process by another event.
In the current example, how we can stop the process (reducing the opacity) upon mouseout event.
Declare your id variable outside the function. Then you can call clearInterval(id) from your mouseout handler.
Note that you don't really need the test() function, you can put its contents directly in your mouseover handler:
var id,
el = document.getElementById("test");
el.addEventListener('mouseover', function(){
var opacity = 1;
id = setInterval(function() {
opacity = opacity - 0.1;
el.style.opacity= opacity;
if(opacity == 0) {clearInterval(id);}
}, 500);
});
el.addEventListener('mouseout', function() {
clearInterval(id);
});
var el = document.getElementById("test"),
opacity = 1,
id;
el.addEventListener('mouseover', function(){
id = setInterval(function() {
opacity = opacity - 0.1;
el.style.opacity= opacity;
if(opacity == 0) {clearInterval(id);}
}, 500);
});
el.addEventListener("mouseout", function() {
clearInterval(id);
});