I was looking around SO and couldn't really find a good concrete answer. My problem is that when the .mouseenter(function(){ }) is fired and the .mouseleave(function(){ }) is fired right after it completes both animation, instead I want the .mouseleave(function(){ }) to stop the .mouseenter(function(){ }) from finishing it's animation.
Here' a jsfiddle of how I currently have it.
HtML:
<div id="header">
<div id="header-align">
</div>
</div>
CSS:
#header {
width: 100%;
height: 200px;
position: fixed;
top: -170px;
}
#header #header-align {
width: 400px;
height: 100%;
border: 1px dotted #000;
margin: 0 auto 0;
}
jQuery
$("#header").mouseenter(function(){
$(this).animate({ top: -20 }, {
duration: 'slow',
easing: 'easeOutBack'
})
});
$("#header").mouseleave(function(){
$(this).animate({ top: -170 }, {
duration: 'slow',
easing: 'easeOutBack'
})
});
I was thinking something like bind(function(){ }) or something like .stopPropagation() but couldn't find a good answer
Did you try adding in a .stop()?
$(this).stop().animate({ top: -170 }, {
duration: 'slow',
easing: 'easeOutBack'
})
jsFiddle
You may also consider using .hover().
$("#header").hover(function(){
$(this).stop().animate({ top: -20 }, {
duration: 'slow',
easing: 'easeOutBack'
})
},
function(){
$(this).stop().animate({ top: -170 }, {
duration: 'slow',
easing: 'easeOutBack'
})
});
Related
I'm trying to find the most concise way to throttle a hover function with jQuery. There are many examples of this but they all seem to not work as intended. For example the use of $.throttle doesn't error but it stops the animation from working altogether. This is the code which I'm trying to throttle:
jQuery(document).ready(function($){
var $navTab = $('.nav-tab-parent');
function moveNavTab(e) {
TweenLite.to($navTab, 0.3, {
css: {
left: e.pageX,
top: e.pageY
}
});
}
$(window).on('mousemove', moveNavTab);
$(".toggle-bars").hover( // this is the .hover() function I need to throttle.
function() {
$(".nav-tab-parent").animate({
opacity: 1
});
$(".nav-tab-parent").delay(10).animate({
width: "36px",
easing: "swing"
});
$(".nav-tab").html("MENU");
$(".nav-tab").delay(350).animate({
opacity: 1
});
}, function() {
$(".nav-tab").animate({
opacity: 0
});
$(".nav-tab-parent").delay(150).animate({
width: "0",
opacity: 0,
easing: "swing"
});
}
);
});
I must be missing something here but can't figure it out. Any help in achieving this would be greatly appreciated!
Changed to use entirely GSAP and relying on .timescale() see the documentation — didn't know the underlying structure so will need some configuring but the basis is there. GSAP has a crazy deep documentation but should be familiar enough to jquery with object animations.
var tl = gsap.timeline().timeScale(-1);
tl.fromTo(".nav-tab-parent", {
autoAlpha: 0,
duration: 1
}, {
autoAlpha: 1,
duration: 1
});
$(".toggle-bars").hover(function() {
tl.timeScale(1);
}, function() {
tl.timeScale(-1);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="toggle-bars">.toggle-bars
<div class="nav-tab-parent">.nav-tab-parent</div>
</div>
I suppose you are trying to achieve something like this. You could try to use .stop() method - it will stop current animation and after that you can run next one. Try to play with arguments to choose what best will suit your case.
let $hover = $('.hover-box'),
$target = $('.animated-box');
function show() {
$target.stop(true, true).animate({
opacity: 1,
})
}
function hide() {
$target.stop(true, true).animate({
opacity: 0
})
}
$hover.hover(show, hide)
.hover-box,
.animated-box {
width: 100px;
height: 100px;
border-radius: 8px;
}
.hover-box {
border: 1px solid #ddd;
display: inline-flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
font-family: sans-serif;
cursor: pointer;
margin-bottom: 16px;
}
.hover-box:hover {
background: #ddd;
}
.animated-box {
opacity: 0;
background: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='hover-box'>Hover</div>
<div class='animated-box'></div>
I've recently started working with Anime.js to animate my designs and I´ve been stuck in this for a while now, bet for many this is very simple!
I have a button that enlarges my div and would like to have the div in its initial state if the icon is clicked again.
My HTML:
var boxGetsLarger = anime({
targets: '.agent-button',
width: {
value: '+=300',
duration: 200,
easing: 'linear'
},
borderRadius: {
value: 83
},
duration: 200,
height: {
value: '+=20'
},
easing: 'linear',
autoplay: false
});
document.querySelector('.agent-button').onclick = boxGetsLarger.play;
.agent-button {
display: flex;
justify-content: space-between;
border-radius: 100px;
background: #ffffff;
box-shadow: 0pt 2pt 10pt #0000001f;
height: 91px;
width: 91px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<div class="agent-button close">
<img src="img/audio-bars.svg">
</div>
It is shame there is no built-in toggle function but there is a reverse function what this does is toggle the internal attribute reversed which, in turn, controls what the play function does.
In theory, you can just call reverse after play like so
var boxGetsLarger = anime({
targets: '.agent-button',
width: {
value: '+=300',
duration: 200,
easing: 'linear'
},
borderRadius: {
value: 83
},
duration: 200,
height: {
value: '+=20'
},
easing: 'linear',
autoplay: false
});
document.querySelector('.agent-button').onclick = function() {
boxGetsLarger.play();
boxGetsLarger.reverse();
}
.agent-button {
display: flex;
justify-content: space-between;
border-radius: 100px;
background: #ffffff;
box-shadow: 0pt 2pt 10pt #0000001f;
height: 91px;
width: 91px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<div class="agent-button close">
<img src="img/audio-bars.svg">
</div>
Only I found reverse was running before play was finished leading to some strange behaviour, I'd recommend taking advantage of the 'finished' promise built-in like so
var boxGetsLarger = anime({
targets: '.agent-button',
width: {
value: '+=300',
duration: 200,
easing: 'linear'
},
borderRadius: {
value: 83
},
duration: 200,
height: {
value: '+=20'
},
easing: 'linear',
autoplay: false
});
document.querySelector('.agent-button').onclick = function() {
boxGetsLarger.play();
boxGetsLarger.finished.then(() => {
boxGetsLarger.reverse();
})
}
.agent-button {
display: flex;
justify-content: space-between;
border-radius: 100px;
background: #ffffff;
box-shadow: 0pt 2pt 10pt #0000001f;
height: 91px;
width: 91px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<div class="agent-button close">
<img src="img/audio-bars.svg">
</div>
This will now only reverse the direction when play is finished.
I hope you find this helpful.
I use this to toggle anime.js animations on a single button.
To initiate reverse() the animation must have run once. You can check this by evaluating the property: 'began'. The first time your animation runs this property will be set 'true'.
console.log(boxGetsLarger); // began: false
document.querySelector('.agent-button').onclick = function() {
boxGetsLarger.play();
if (boxGetsLarger.began) {
boxGetsLarger.reverse();
}
console.log(boxGetsLarger); // began: true
}
What fixed it for me was juliangarnier/anime#577 (comment):
I encountered this issue today, here is my solution as a pen.
I think the confusion arises from when animations are paused, and how the reverse() method works:
Non-looped animations are automatically paused when they reach the end (or beginning when reversed).
The reverse() method only changes the playback direction, and doesn't unpause a paused animation.
Doing reverse() on an animation while it is in progress means it will continue to play in the opposite direction, but if the animation is at the beginning/end (i.e. paused), you will also need to do play() to get it started again.
From his linked CodePen:
function toggle() {
if (anim.began) {
anim.reverse()
if (anim.progress === 100 && anim.direction === 'reverse') {
anim.completed = false
}
}
if (anim.paused) {
anim.play()
}
}
Give this a try: (from docs)
boxGetsLarger.reverse();
I used this to toggle back and forth between an "open" state and a "closed" state.
const toggle = (animation, open) => {
if (open) {
animation.play();
if (animation.reversed) {
animation.reverse();
}
} else {
animation.play();
if (!animation.reversed) {
animation.reverse();
}
}
}
i want to move box right then left and again right left continously but it make only one cycle
$(document).ready(function() {
function a() {
$('#foo').css({
'right': window.innerWidth - $('#foo').width(),
'left': 'auto'
}).animate({
'right': '0px'
}, 9000, function() {
$('#foo').animate({
'left': '0px'
}, 9000, a);
});
}
a();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" style="background: red; width: 100px; height: 100px; position: absolute" ></div>
any help ??
Yes, it works without any problem.
$(document).ready(function() {
function a() {
$('#foo').css({
'right': window.innerWidth - $('#foo').width(),
'left': 'auto'
}).animate({
'right': '0px'
}, 9000, function() {
$('#foo').animate({
'left': '0px'
}, 9000, a);
});
}
a();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" style="background: red; width: 100px; height: 100px; position: absolute" ></div>
https://jsfiddle.net/n7u7q42d/
Probably you have loaded multiple libraries. Could you post errors please?
Your code already does what you are asking for:
$(document).ready(function() {
function a() {
$('#foo').css({
'right': window.innerWidth - $('#foo').width(),
'left': 'auto'
}).animate({
'right': '0px'
}, 9000, function() {
$('#foo').animate({
'left': '0px'
}, 9000, a);
});
}
a();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" style="background: red; width: 100px; height: 100px; position: absolute" ></div>
But, you can also accomplish the same thing with much better performance if you use use CSS animations:
#foo {
background: red;
width: 100px;
height: 100px;
position: absolute;
left:0px; /* This is the property that will be animated */
animation:9s leftRight infinite; /* configure the animation */
}
#keyframes leftRight {
0% {
left:0;
}
50% {
left:calc(100% - 100px);
}
100% {
left:0;
}
}
<div id="foo"></div>
The animation itself is working but why isn't my complete function working?
fiddle: https://jsfiddle.net/jzhang172/5kfbw066/1/
$(".ok").animate({
height:"300px"
},{
duration:2000
}, {complete:function(){
alert('hey');
}
});
.ok{
background:blue;
height:100px;
width:200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ok"></div>
complete is a property just as duration
$(".ok").animate({
height: "300px"
}, {
duration: 2000,
complete: function() {
alert('hey');
}
});
.ok {
background: blue;
height: 100px;
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ok"></div>
complete callback should be passed as the method on the second param object to the animate(), not as a different object.
Updated Fiddle
$(".ok").animate({
height: "300px"
}, { // <--- Pass `complete` callback as part of this object.
duration: 2000,
complete: function() {
alert('hey');
}
});
$(".ok").animate({
height: "300px"
}, { // <--- Pass `complete` callback as part of this object.
duration: 2000,
complete: function() {
alert('hey');
}
});
.ok {
background: blue;
height: 100px;
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ok"></div>
Or, it can also be passed as last parameter to animate
$(".ok").animate({
height: "300px"
}, 2000,
function() {
alert('hey');
}
);
$(".ok").animate({
height: "300px"
}, 2000,
function() {
alert('hey');
}
);
.ok {
background: blue;
height: 100px;
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ok"></div>
I am trying to alternate display between two containers on a page using fadeOut/fadeIn & slideUp/slideDown. I would like the transition from the first container to the second to look the same as the transition from the second to the first; they fade in/out respectively, the current container slides up and away, and the other slides up from below it, all simultaneously. The first button triggers the animation described, but when I use the second button to transition to the first element the first element suddenly pops into existence while fading in jerking the page down, the second fades out, but no slide occurs. Thanks for your help, and let me know if I can clarify for you!
var main = function () {
$('.button-1').click(function () {
$('.container-1').fadeOut({ duration: 1400, queue: false }).slideUp(1400);
$('.container-2').fadeIn({ duration: 1400, queue: false }).slideDown(1400);
});
$('.button-2').click(function () {
$('.container-2').stop(true, true).fadeOut({ duration: 1400, queue: true }).slideUp(1400);
$('.container-1').fadeIn({ duration: 1400, queue: false }).slideDown(1400);
});
$(document).ready(main);
you actually only need 1 button to do this if you animate the height and opacity with toggle. ive added it twice since your use case was for 2 buttons
js fiddle here
js
var main = function () {
$('.button-1').click(function () {
$('.container-1')
.stop(true, true)
.animate({
height: "toggle",
opacity: "toggle"
}, 1400);
$('.container-2')
.stop(true, true)
.animate({
height: "toggle",
opacity: "toggle"
}, 1400);
});
$('.button-2').click(function () {
$('.container-2')
.stop(true, true)
.animate({
height: "toggle",
opacity: "toggle"
}, 1400);
$('.container-1')
.stop(true, true)
.animate({
height: "toggle",
opacity: "toggle"
}, 1400);
});
}
$(document).ready(main);
html
<div class=container-1>container1</div>
<div class=container-2>container2</div>
<input type=button class=button-1 value=button1>
<input type=button class=button-2 value=button2>
css
.button-1 {
color: red;
}
.button-2 {
color: blue;
}
.container-1, .container-2 {
width: 100px;
height: 100px;
}
.container-1 {
background-color: green;
}
.container-2 {
display: none;
background-color: orange;
}
Not sure if this is what you want. But here is one way to switch between two containers with slide and fade at the same time:
HTML:
<input type="button" class="redclick" value="Red"></input>
<input type="button" class="blueclick" value="Blue"></input>
<div class="red"></div>
<div class="blue"></div>
CSS:
.red, .blue{
width:200px;
height:200px;
position: absolute;
}
.red{ background:red; }
.blue{ background:blue; }
Javascript:
$(function() {
$('.red').hide();
$('.blue').show();
$(".blueclick").click(function() {
if($('.red').css('opacity') == '1'){
$('.red').fadeOut({ duration: 1400, queue: false }).slideUp(1400);
$('.blue').slideDown({ duration: 1400, queue: false }).fadeIn(1400);
}
});
$(".redclick").click(function() {
if($('.blue').css('opacity') == '1'){
$('.blue').fadeOut({ duration: 1400, queue: false }).slideUp(1400);
$('.red').slideDown({ duration: 1400, queue: false }).fadeIn(1400);
}
});
});
JSFiddle Demo
Hope this helps.