Slidingbar .js animation not smooth - javascript

I just built a sliding top panel for a website which is running on wordpress. Therefore I've added the bar into the header by using a hook point. I use a very simple custom.js (mostly copied together from different sources), so that the bar will "slide down" (=appear) on first click and "slide up" (=disappear) on the second click. For some reasons, this animation is not running smoothly. While it is a little bit too fast (which I could easily change by increasing the speed duration), the animations also seems to be laggy. I bet, I oversee something important, cause I am not used to jQuery/Javascript. Exists there some of code snippets to make the transition more smoothly?
Java-Script Markup:
// Slidingbar initialization
var tgslidingbar_state = 0;
// Clicking
jQuery( '.tg-toggle-wrapper' ).click( function(){
var $tgslidingbar = jQuery ( this ).parents( '#tgslidingbar-area').children( '#tgslidingbar' );
//Expand
if ( tgslidingbar_state === 0 ) {
$tgslidingbar.slideDown( 340, 'easeOutQuad' );
jQuery( '.tg-toggle-wrapper' ).addClass( 'open' );
tgslidingbar_state = 1;
//Collapse
} else if( tgslidingbar_state == 1 ) {
$tgslidingbar.slideUp(340,'easeOutQuad');
jQuery( '.tg-toggle-wrapper' ).removeClass( 'open' );
tgslidingbar_state = 0;
}
});
HTML-Markup:
<div id="tgslidingbar-area" class="tgslidingbar-area">
<div style="display: none;" id="tgslidingbar">
<div class="containertop">
Slidingbar Content Here!
</div></div>
<div class="tg-toggle-wrapper"><a class="tg-toggle" href="#"></a>
</div></div>
With this markup the sliding bar does slide down and up. For example, I've added a google maps into the sliding bar, when I've noticed that the bar is laggy. Could this be a reason for the laggy animations, too, cause google maps just loads when the bar opens? I also realized the "easeOutQuad" property in the copied snippet animations and searched for this on the web. It seems to be a popular jQuery library for animations. Up to now I do not have included this library into my websites, maybe thats the cause?
Kind Regards from Germany!

I applied some modification on the code.
I use query’s animate function.
A initial display property of #tgslidingbar was changed to ‘block’
added ‘padding’ on container top class and removed ‘padding’ on tgslidingbar class.
https://jsfiddle.net/nigayo/cn49ubr6/
[html]
<div style="display:block;height:0" id="tgslidingbar">
[JS]
var tgslidingbar_state = 0;
var $tgslidingbar = jQuery('#tgslidingbar');
var nHeight = $tgslidingbar.get(0).scrollHeight;
// Handle the slidingbar toggle click
jQuery('.tg-toggle-wrapper').click(function() {
//Expand
if (tgslidingbar_state === 0) {
$tgslidingbar.animate({
'height': nHeight
}, 340, function() {
jQuery('.tg-toggle-wrapper').addClass('open');
tgslidingbar_state = 1;
});
......

I suggest some different options.
first,
Instead, use jquery's animate function.
http://api.jquery.com/animate/
sample code : https://jsfiddle.net/nigayo/jo5vd2ob/
second.
you can use css transition.
http://jsfiddle.net/nigayo/qy1ummx6/1/
[css]
.box {
float: left;
/* you can use other ease effect. ease-in, ease-out, ease-in-out */
-webkit-transition: all 1s ease;
overflow: hidden;
}
.height {
background-color: red;
width: 300px;
max-height: 0px;
}
.change {
max-height: 500px;
}
[JS]
$('button').on('click', function() {
$('.box').toggleClass('change');
});

Related

Opacity transition works on fade out, but not fade in

This is frustrating me to no end. Before I post the code, here's a summary:
The goal, in simple terms: when I double click X, I want it to fade out; when I click Y, I want X to fade in.
The method: I'm using CSS to create the actual fade-in and fade-out "animations." I'm using JavaScript to apply the classes when necessary using a little trickery.
The problem: the fade-in transition doesn't work -- the element just appears instantly. What is driving me insane is the fact that the fade-in, when instantly added back onto a faded-out object, works perfectly. I'll explain this better as a comment in the JS code.
(Yes, I've added opacity: 1 and transition: opacity onto the base elements. It had no effect at all.)
The code:
CSS
*.fade-out {
opacity: 0;
transition: opacity 400ms;
}
*.fade-in {
opacity: 1;
transition: opacity 400ms;
}
*.hide {
display: none;
visibility: hidden;
}
JavaScript
$( '#ArtistEmblem' ).on( 'dblclick', function() {
fadeOut($( '#ArtistEmblem' ));
fadeIn($( '#btnShowLogo' ));
});
$( '#btnShowLogo' ).on( 'click', function() {
fadeOut($( '#btnShowLogo' ));
fadeIn($( '#ArtistEmblem' ));
});
function fadeOut(element) {
element.addClass( 'fade-out' );
setTimeout( function () {
element.addClass( 'hide' );
/*
* I tried immediately adding the 'fade-in' class here
* and it worked -- as soon as the element faded out, it faded
* back in (using the CSS transition). However, outside of this,
* it REFUSES to work; everything appears instantly
*/
console.log('timer triggered');
}, 400);
}
function fadeIn(element) {
element.removeClass( 'hide' );
element.removeClass( 'fade-out' );
element.addClass( 'fade-in' );
}
Relevant HTML
<div id="ArtistEmblem">
<img src="img/logo_artist_2.png" />
</div>
<div id="PopMenu" class="collapse">
<article>
<header>
<b>Debug Menu</b>
</header>
<section>
<button id="btnOpenOverlay">Open Overlay</button>
<button id="btnShowLogo" class="hide">Show Logo</button>
<button id="btnClose">Close Menu</button>
</section>
</article>
</div>
I apologize if this is something obvious but I've wasted far too much time trying to solve it. I am also open to better, faster, or more efficient solutions if that would be the best answer. Thanks in advance!
The problem is that the initial opacity of "hidden" element is 1 by default. You just need to set it to 0. And also remove display: none –
*.hide {
opacity: 0;
}
Also I would do a little refactoring and remove setTimeout:
$('#ArtistEmblem').on('click', function() {
fade($('#btnShowLogo'), $(this));
});
$('#btnShowLogo').on('click', function() {
fade($('#ArtistEmblem'), $(this));
});
function fade(inElement, outElement) {
inElement.removeClass('hide');
inElement.addClass('fade-in');
outElement.removeClass('fade-in');
outElement.addClass('fade-out');
}
If you don't want the hidden element to occupy space and you want it to be displayed-none, then you need to set display: block before starting the fadeOut.
I know you're asking for a JS heavy answer, but I highly recommend toggling a class of "active", "open" or something similar and using CSS with the transition. Less is more here.
Here's an example fiddle of something I've transitions not only the opacity, but also the z-index. That's the key with these transitions if you intend on having any elements below such as buttons that require hovering, clicking, etc.
JS Fiddle
Key parts:
.container {
z-index: -1;
opacity: 0;
transition: z-index .01s 1s, opacity 1s;
}
.container.active {
transition: z-index 0s, opacity 1s;
z-index: 500;
opacity: 1;
}
EDIT
I was just messing around with this type of thing for my own project, and observing how beautiful Stripe handles their navigation bar. Something so simple changes everything, and that's pointer-events. If you're okay with its support, (notable no ie. 10) this is infinitely easier to integrate. Here's another fiddle of the simulation in a nav bar.
The key part is pointer-events: none, as it ignores click events if set to none, almost as if it wasn't there, yet visibly it is. I highly recommend this.
https://jsfiddle.net/joshmoxey/dd2sts7d/1/
Here is an example using Javascript Animate API. Animate API is not supported in IE/Edge though.
var element = document.getElementById("fade-in-out")
var button = document.getElementById("x")
button.addEventListener("click", function(event) {
element.animate([{opacity: 1, visibility: "visible"},{opacity: 0, visibility: "hidden"}], {duration: 2000})
setTimeout(function() { element.remove() }, 2000)
})
button.addEventListener("dblclick", function(event) {
element && element.animate([{opacity: 0}, {opacity: 1}], {duration: 2000})
})
<input id="x" type="button" value="Click here" />
<div id="fade-in-out"> FADE ME </div>

Why is Jquery animate() not working in my case?

I have the following HTML layout:
<html>
<head>
...
</head>
<body>
<header class="fluid-container">
<div class="nav-wrapper">
...
</div>
</header>
<section class="salutation fluid-container">
<div class="intro-wrapper">
...
</div>
</section>
</body>
</html>
My objective is to hide intro-wrapper whenever my window scrolls more than 60px and vice-versa. Hence I have implemented the following Jquery code to achieve the above.
var checkScroll = true;
$(window).scroll(function() {
if($(this).scrollTop() > 60 && checkScroll) {
$(".intro-wrapper").stop().animate({display:'none'}, 400);
checkScroll = false;
console.log('Scrolling down. \t checkScroll: ' + checkScroll);
}
else if($(this).scrollTop() < 60 && !checkScroll) {
$(".intro-wrapper").stop().animate({display:'block'}, 400);
checkScroll = true;
console.log('Scrolling up. \t\t checkScroll: ' + checkScroll);
}
});
But unfortunately, I have been failing miserably at understanding why the animation isn't taking place. Please point out the mistake in my above code and help me figure out the solution.
Please note that console.log() is presenting results just as expected, i.e., the conditions are getting appropriately fulfilled and the loop is appropriately completing its journey.
display will/does not work with animate. You can instead use show() and hide() in addition to the other answer.
From http://api.jquery.com/animate/:
Note: Unlike shorthand animation methods such as .slideDown() and .fadeIn(), the .animate() method does not make hidden elements visible as part of the effect. For example, given $( "someElement" ).hide().animate({height: "20px"}, 500), the animation will run, but the element will remain hidden.
Instead of animate here you can use jquery .fadeIn() .fadeOut() method to show or hide element with a delay.
Display property won't works in jQuery animate.
Refer animate
display to none/block cannot be animated. Try instead animate the height to 0 with overflow: hidden
Or you can do it with css transitions easily:
// hide it
$(".intro-wrapper").addClass('hidescroll');
// show it again
$(".intro-wrapper").removeClass('hidescroll');
And then in css:
.intro-wrapper {
transition: height .5s ease-in;
height: 400px;
}
.intro-wrapper.hidescroll {
height: 0;
overflow: hidden;
}

jQuery hover animation efficiency

I've got my hover working - but i'm interested in trying to make it more efficient as it does seems to 'lag' when it's finding the .overlay div. I also had the issue where I was animating all .overlay divs on a page, which I consider to be quite a noob mistake.
Anyway, let's learn how to make the below better!
jQuery:
// get aside feature
var aside_feature = $('aside .feature');
// on hover, fade it in
$( aside_feature ).hover(function() {
// get the overlay div
var feature_overlay = $(this).find('.overlay');
$(feature_overlay).stop().fadeIn();
// on hover out, fade it out
}, function() {
$(this).find('.overlay').stop().fadeOut();
});
Markup:
<aside>
<div class="feature">
<div class="overlay">
button
</div><!-- overlay -->
<div class="text">
<p>text</p>
</div><!-- .text-->
<div class="image">
<figure>
<img src="" alt="">
</figure>
</div><!-- .image -->
</div><!-- .feature -->
</aside><!-- aside -->
Fiddle: http://jsfiddle.net/9xRML/5/
Edit - Final Code
Thanks #Shomz, and #Afro.
Final code choices were to use tranisitons, and coupled with modernizr detection for transitions, I changed my hidden overlay div to opacity: 0; *display:none; and javascript as a fallback:
CSS
.overlay {
*display: none;
opacity: 0;
transition: 0.4s all linear;
}
.overlay:hover {
opacity: 1;
}
jQuery
$(function () {
/*=====================================
= Feature overlay =
=====================================*/
if (!Modernizr.csstransitions) {
// get aside feature
var aside_feature = $('aside .feature');
// on hover, fade it in
$( aside_feature ).hover(function() {
$(this).find('.overlay').stop(true, true).fadeIn();
// on hover out, fade it out
}, function() {
$(this).find('.overlay').stop(true, true).fadeOut();
});
}
});
With risking of having my answer out of scope here, if you want to really get performance, you should switch to CSS animations. It's totally possible with your example by setting the default opacity of the overlay to 0 (instead of display: none;) and making it show up on .feature:hover. The trick is to add the transition property like this:
// applies a 4ms transition to any possible property with no easing
transition: all .4s linear;
See the whole example here: http://jsfiddle.net/9xRML/6/
See a nice article about the performance difference (CSS vs. JS) here: http://css3.bradshawenterprises.com/blog/jquery-vs-css3-transitions/ (there are many more, of course)
I think I have solved your issue using the same HTML but changing the following:
JQuery
$('aside .feature').hover(function() {
$(this).find('.overlay').stop(true, true).fadeIn();
}, function() {
$(this).find('.overlay').stop(true, true).fadeOut();
});
CSS
.feature {
background: #ccc;
}
.overlay {
display: none;
}
This means the overlay will only display on hover.
Details on .stop() can be found here.
.stop(true, true)
We can create a nice fade effect without the common problem of multiple queued animations by adding .stop(true, true) to the chain.
DEMO

How to initialize an Angularjs css3 animation using Javascript

I am currently trying to do a CSS3 animation in Angular.js.
Before animating I try to set the initial css properties using Javascript.
So, is there a way to initialize an animation using Javascript and then continue the animation using CSS3?
My situation:
When the user clicks on a div, a dialog should appear.
The dialog should start out exactly over the original div (same size, same position), and then grow to a larger size.
I am able to animate the dialog from a predefined position and size:
CSS:
.dialog {
position: absolute;
z-index: 10;
width:600px;
height:400px;
margin-left: -300px;
left:50%;
margin-top: 50px;
}
.dialogHolder.ng-enter .dialog {
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1s;
width:0;
height:0;
margin-left: 0px;
}
.dialogHolder.ng-enter-active .dialog {
width:600px;
height:400px;
margin-left: -300px;
}
I would like to animate the dialog starting at the size of the clicked div.
So far my code (not working yet) looks like this:
HTML:
<div ng-repeat="course in data.courses" ng-click="showDialog($event)">
{{ course.cursus }}
</div>
<!-- Placeholder for blokDialogs -->
<div class="dialogHolder" ng-include="dialogTemplate.url">
DIALOG WILL BE LOADED HERE
</div>
Javascript:
app.controller('blockController', function($scope) {
$scope.showDialog = function(evt) {
// get position and size of the course block
$scope.dialogTemplate.clientRect = evt.target.getBoundingClientRect();
// load the html to show the dialog
$scope.dialogTemplate.url = 'partials/blokDialog.html';
// SHOULD I DO SOMETHING HERE?
};
});
// OR SHOULD I DO SOMETHING LIKE THIS?
app.animation('.dialogHolder', function(){
return {
// SOMEHOW SET THE WIDTH, HEIGHT, TOP, LEFT OF .dialog
};
});
I'd prefer to do this without jQuery to keep the page weight low.
Regards,
Hendrik Jan
You want to use ng-animate http://docs.angularjs.org/api/ngAnimate
If you are using ng-repeat, you can animate when elements enter, leave and move around your repeater. The magic is that you don't even have to put an extra directive in your html, just define your CSS animations accordingly.
So in your case something like this
.repeater.ng-enter, .repeater.ng-leave, .repeater.ng-move {
-webkit-transition:0.5s linear all;
transition:0.5s linear all;
}
.repeater.ng-enter { }
.repeater.ng-enter-active { }
.repeater.ng-leave { }
.repeater.ng-leave-active { }
.repeater.ng-move { }
.repeater.ng-move-active { }
and your HTML
<div ng-repeat="..." class="repeater"/>
In the end, I found the following solution:
HTML:
Create an onClick handler and a placeholder where the dialog is loaded.
<!-- Element on which the user clicks to initialize the dialog -->
<div ng-repeat="course in data.courses"
ng-click="showDialog($event, course)">
{{ course.name }}
</div>
<!-- Placeholder for blokDialogs -->
<div class="dialogHolder"
ng-include="dialogTemplate.url"
onload="showDialogLoaded()">
</div>
HTML Template:
partials/blokDialog.html sets it's style using ng-style.
<div ng-style="dialogTemplate.initialStyle">
...
</div>
Javascript:
The onClick handler sets the initial CSS before the animation starts.
$scope.showDialog = function(evt, course) {
// Load the dialog template
$scope.dialogTemplate.url = 'partials/blokDialog.html';
// set the css before the animation starts
// get position and size of the course block
var clientRect = evt.target.getBoundingClientRect();
$scope.dialogTemplate.initialStyle = {
left: clientRect.left + 'px',
top: clientRect.top + 'px',
width: clientRect.width + 'px',
height: clientRect.height + 'px',
backgroundColor: getComputedStyle(evt.target).backgroundColor
};
};
The style needs to be removed before the animation ends but after the animation started.
The animation starts at the end of the onLoad handler. If we remove the style in the onLoad handler (i.e. in showDialogLoaded), then we are to early.
We use setTimeout to make sure that the removal of the style is done after the animation was started.
$scope.showDialogLoaded = function() {
// remove the style that we set in showDialog
setTimeout(function(){
$scope.dialogTemplate.initialStyle = {};
// we need to $apply because this function is executed
// outside normal Angular handling, so Angular does not know
// that it needs to do a dirty check
$scope.$apply();
}, 0);
};
I hope this can be helpful for others.
Regards,
HJ

Trying to fade and slide text out of initials on mouse over with jQuery

I'm trying to create an effect with jQuery where on mouse over of my initials on the page in the header, the div they are in expands (using jQuery animate) and the text of my full name fades in from each initial.
I have tried a variety of things but am not sure what is the best way to do this. I'm a bit stuck. I'm currently trying to get it going by having the initials of my name "OW" in two separate divs and then the remainder of my name to make up "wen" and "illiams" in between those initals. Like so:
<div class="initialF inlinediv">O</div>
<div class="fullF inlinediv">wen</div>
<div class="initialL inlinediv">W</div>
<div class="fullL inlinediv">illiams</div>
I thought it would work to use jQuery slideLeft and .fadeIn to get the text to slide in from the left as well as fading to look like the text is emerging from the initials but the animations was jumpy and would go onto a second line while the div was still expanding. I am using the below jQuery to detect the mouseIn/Out events:
<script>
$(".brand").mouseenter(function() {
$('.brand').animate({width: '160px'});
$('.fullF').fadeIn("slow");
});
$(".brand").mouseout(function() {
$('.brand').animate({width: '36px'});
$('.fullF').fadeOut("slow");
});
</script>
The alternatives I have tried were using jquery.lettering.js to help with it but there seemed to be some issues with that. Any suggestions to push me in the right direction would be useful and my site with a partially working example is here:
http://192.241.203.146/
Here's one using css transitions rather than jquery animate: http://jsfiddle.net/S58Se/2/
<div class='branding'>
<span class='initial'>O</span><span class='hidden nameFull wen'>wen</span>
<span class='initial'>W</span><span class='hidden nameFull illiams'>illiams</span>
</div>
span {
display: inline-block;
overflow: hidden;
transition: all 1s;
-moz-transition: all 1s;
-webkit-transition: all 1s;
}
.wen { width: 36px; }
.illiams { width: 160px; }
span.hidden {
width: 0px;
opacity: 0;
}
$('.branding').hover(
function() { $('.nameFull').removeClass('hidden'); },
function() { $('.nameFull').addClass('hidden'); }
);
Or you can do away with the javascript altogether with this: http://jsfiddle.net/S58Se/3/
remove the js and add these css statements:
.branding:hover .wen {
width: 36px;
opacity: 1;
}
.branding:hover .illiams {
width: 160px;
opacity: 1;
}
... just because I think it's neat.
A good way to go about this is to just expand the use of your call to the animation method by adding another property to the object you are passing in. So instead of calling an extra method (fadeIn) you just handle it all in one fell swoop:
$('.brand').on({
'mouseenter' : function () {
$('.nameFull').stop().animate({
'width' : '200px',
'opacity' : '1'
}, 500);
},
'mouseleave' : function () {
$('.nameFull').stop().animate({
'width' : '0',
'opacity' : '0'
}, 500);
}
});
You'll notice I'm also using 'on' instead of the 'hover' or 'mouseenter' and 'mouseleave' methods. In most recent versions of jQuery those methods just reference 'on', so it's better to just cut out the middle man and do it all in one place.
I'm not sure if this exactly fits your design, but I made a Codepen to demonstrate the code in action: http://codepen.io/Tristan-zimmerman/pen/lnDGh
Style the hidden divs position:absolute, and when show them:
'show' them first, to set them visible
then position them (next to your 'launching' div), using jQuery.position();
set the animation going.
Essentially you want them 'absolute' to avoid them thunking in/out & changing your existing flow. position() must be called after making the element visible, and then you should have appropriate starting conditions to kick off your animation.
Or you could try using <span>' for the incoming text and/or displaying as inline-block, which may help avoid the "incoming" kicking things down a line. HTH.
I think what you are looking for is something like this: JSFiddle
html:
<div class="brand">
<div>O<span class="full">wen </span>W<span class="full">illiams</span></div>
</div>
jq:
$('.brand').hover(function(){
$(this).stop().animate({width: '160px'},'slow',function(){
$(this).children('div').children('.full').stop().fadeIn('slow');
});
},function(){
$(this).children('div').children('.full').stop().fadeOut('slow',function(){
$(this).parent().parent().stop().animate({width: '36px'},'slow');
});
});
css:
.full{
display: none;
}
note: there is a simple bug that happens in a specific case and I'm working on it.
regards,

Categories