Click through div and fade out on mouse over - javascript

I have a navbar on the top of the page, and when certain events run, I have a header that pops up for about 3 seconds. During this time you cannot click on the underlying nav links.
.alert-header{
pointer-events: none;
}
I tried doing a css transition, but pointer events are set to none. So I tried with jquery (assuming pointer events only affect css):
$(document).on('mouseenter', '.alert-header', function(){
$(this).animate({opacity: 0.2}, 'fast');
}).on('mouseleave', '.alert-header', function(){
$(this).animate({opacity: 1}, 'fast');
});
So, after doing that and testing it, I get the same result as with doing a css transition.
Is there a way where I can fade out the header to 0.2 opacity when the mouse moves over it, and be able to click on the underlying links?

Okay, I have figured out a way. First in the css I turn off pointer events for the div I want to click through:
.alert-header{
pointer-events: none;
}
Next I test the Y position of the mouse when it moves cursor and when the header is visible, if the Y position is less than the height of the header I make it fade, otherwise I fade it back to opaque.
var fadeRunning = false;
$(document).on('mousemove', function(e){
var header = $('.alert-header');
if(header.is(':visible')){
var mouseY = e.pageY;
var height = header.outerHeight();
if(mouseY <= height && !fadeRunning){
fadeRunning = true;
header.animate({opacity: 0.2}, 'fast', function(){fadeRunning=false});
}else{
if(!fadeRunning){
fadeRunning = true;
header.animate({opacity: 1}, 'fast', function(){fadeRunning=false});
}
}
}else{
header.css({opacity: 1});
}
});

Related

How to animate nested content when animated parent slide moves into viewport, not using scroll

I'm looking to use javascript to animate the content of a nested DIV within an parent slide when the parent slide moves into the viewport.
At the moment, the content in the nested DIV only animates once a scroll command is also triggered after the parent slide moves onto the screen. I believe this is because the slide motion is animated and not scroll controlled.
The same issue is at play in this JSFiddle demo I created to explore the issue:
http://jsfiddle.net/9dz3ubL1/
(The animated movement of the slide from right to left in this demo has been created to test for this problem, to replicate the motion of the slide without scrolling; it is not actually a feature of the development proper).
My question is, how can I script for the animations to be triggered for each nested DIV, when each slide element moves into the viewport, without requiring a scroll function?
Thanks for any help. Here's the script I'm using to control opacity and other CSS stylings.
$(document).ready(function() {
/* Every time the window is scrolled ... */
$(window).scroll(function() {
/* Reveal hidden_header delayed */
$('.hidden_header').each(function(i) {
var center_of_object = $(this).offset().left + $(this).outerWidth();
var center_of_window = $(window).scrollLeft() + $(window).width();
/* If the object is completely visible in the window, fade it it */
if (center_of_window > center_of_object) {
$(this).animate({
'opacity': '1'
}, 500);
$(this).animate({
'right': '0'
}, 1500);
}
});
/* Reveal hidden_content delayed */
$('.hidden_content').each(function(i) {
var center_of_object = $(this).offset().left + $(this).outerWidth();
var center_of_window = $(window).scrollLeft() + $(window).width();
/* If the object is completely visible in the window, fade it it */
if (center_of_window > center_of_object) {
$(this).animate({
'opacity': '1'
}, 3000);
$(this).animate({
'bottom': '0'
}, 3500);
}
});
/* Reveal button delayed */
$('.button').each(function(i) {
var center_of_object = $(this).offset().left + $(this).outerWidth();
var center_of_window = $(window).scrollLeft() + $(window).width();
/* If the object is completely visible in the window, fade it it */
if (center_of_window > center_of_object) {
$(this).animate({
'opacity': '1'
}, 5000);
}
});
});
});
If your slide motion is animated fully (not incremental as it is in the jsfiddle you linked) then jQuery provides you with the ability to perform an action after your animation is complete.
http://api.jquery.com/animate/
Look at the options you can use for the animation function. One of them is called done. You can assign a function to the done option and that function will be called when your animation is complete.
Using one of your animates as an example, the syntax may look like this:
$(this).animate({
'opacity': '1'
}, {duration: 3000, done: function () {
//animate some stuff here
}};
Note that I just picked a random animation from your code. I'm not sure exactly when you want to perform the animation of the content, but you can use this technique anywhere you use a jQuery animate.
I've used this before to control nested animations in a slideshow format and it has worked very well! I hope this what you wanted.

Vibrating screen on scroll using transform: scale

I would like a zoom out effect for my header, what loads zoomed in, and on scroll it zoom out.
What I do is to increase the size with transform: scale(1.4) and on scroll I calculate a percentage from the scrollTop and header height and I multiply it with 0.4. The problem is that on scroll the screen starts to vibrate, the scale isn't smooth. Do you have any idea what's wrong with my code or can you tell me what's the best practice to achieve this?
jQuery(document).ready(function(){
function zoom_out() {
var page_header_height = jQuery('#page-header-custom').outerHeight();
var scroll_top = jQuery(window).scrollTop();
var zoom_multiplier = 0.4;
var multiplier = (zoom_multiplier*(1-((scroll_top-jQuery('#page-header-custom').offset().top)/page_header_height))) > 1 ? 1 : (zoom_multiplier*(1-((scroll_top-jQuery('#page-header-custom').offset().top)/page_header_height)));
if(multiplier <= 1) {
jQuery('#page-header-inner').stop(true, true).transition({ scale: 1/(1+multiplier), translate: '0, -50%' });
jQuery('#page-header-custom').stop(true, true).transition({
scale: 1+multiplier
});
}
}
zoom_out();
jQuery(window).on('scroll', function(){
zoom_out();
});
});
I created a JSFiddle to see it in action.
I've updated your Fiddle with smooth scaling using window.requestAnimationFrame. The scale animation is vibrating because you're triggering a translation on each scroll event. Think about it like this:
user scrolls
zoom_out() gets triggered and tells an element to transition it's transform properties. Your element is now transitioning at a certain speed: "length" / transitiontime.
More scroll events have passed and are all triggering zoom_out(). The next transition will probably happen at a different speed, resulting in 'vibrating' animation.
First you can get rid of jQuery's transition() method. If you fire the function at 60fps or close to 60fps it will appear to animate smoothly to the human eye, without the need of transitioning or animating.
if(multiplier <= 1) {
//jQuery('#page-header-inner').stop(true, true).transition({ scale: 1/(1+multiplier), translate: '0, -50%' });
//jQuery('#page-header-custom').stop(true, true).transition({ scale: 1+multiplier });
//becomes:
jQuery('#page-header-inner').css({ scale: 1/(1+multiplier), translate: '0, -50%' });
jQuery('#page-header-custom').css({ scale: 1+multiplier });
}
}
Getting the function triggered at ~60fps can be achieved in multiple ways:
Throttle your scroll event to 60fps.
Or use window.requestAnimationFrame like in the updated Fiddle
function zoom_out(){
//calculation code & setting CSS
window.requestAnimationFrame(zoom_out);
}
//trigger it once instead of the scroll event handler
window.requestAnimationFrame(zoom_out);

Bootstrap Modal Fade Out Animation

I've added some basic animation to the closing of the modal box, so that it zooms out to an element:
$(function(){
var $modal = $('.modal');
$modal.on('hide', function () {
if (!$modal.isAnimating) {
// $('.modal-backdrop.in').fadeTo(250, 0); // fade out backdrop
var $target = $('#zoomout-target');
var pos = $target.offset();
pos.top -= $(window).scrollTop();
pos.left -= $(window).scrollLeft();
$modal.css({top: pos.top, left: pos.left, transform: 'scale(0.1, 0.1)', opacity: 0});
$modal.isAnimating = true;
setTimeout(function(){
$modal.modal('hide');
$modal.isAnimating = false;
}, 750);
return false;
}
$modal.css({top: '', left: '', transform: '', opacity: ''});
});
});
The problem is that the backdrop "hides" the target element to which the modal box zooms out.
So I added the commented line above $('.modal-backdrop.in').fadeTo(250, 0); which fades out the backdrop very nicely, but it looks like I'm missing something because then the page freezes.
It seems like the backdrop is still on, capturing all of the mouse events, etc, even though transparent. So the backdrop is not visible, but is making the page unusable.
How can I get rid of the backdrop at the end of the fadeTo animation?
EDIT:
I noticed that the problem is with the .modal-backdrop and .modal-scrollable overlays, so this snippet instead of the offensive one resolves the issue, but there's has to be a cleaner solution IMO:
$('.modal-backdrop.in').fadeOut(600, function(){
$('body').removeClass('modal-open');
$('.modal-backdrop').hide();
$('.modal-scrollable').hide();
}); // fade out backdrop
I'm using Bootstrap 2.3.2 and Bootstrap Modal 2.2.5
TIA

Full page slider with native scrollbar

I am building a full page slider that keeps the native scrollbar and allows the user to either free scroll, use the mouse wheel or navigation dots (on the left) to switch to a slide.
Once the user is on the last slide and tries to scroll down further, the whole slider moves up to reveal a simple scrollable section. If the user scrolls down and then tries to go back up, then this new section moves out of the way again and returns the slider back into view.
Fiddle: http://jsfiddle.net/3odc8zmx/
The parts I'm struggling with:
Only the first two navigation dots work. The third one DOES WORK if you area looking at the first slide. But doesn't do anything, if you are on slide 2. Note: the purple one is a short-cut to the second section of the page and not related to the slider.
When moving to the last slide (via the dots, if you're on the first slide) it causes the code to make the whole slider move upwards as it sees this as the user has slid past the last slide as per the description above. I have tried to combat this using a variable called listen to stop the scroll event listening when using the showSlide method... but it seems to be true even though I set it to false, and only reset it to true again after the animation...
When scrolling down using the mouse wheel, I can get to the second section and back up, but not to the first third section. I'm wondering if I could use the showSlide method to better handle this instead of the current dirty next and prev functions I have implemented.
Note: If the user has free-scrolled, when they use the mouse-wheel, I want the slider to snap to the nearest slide to correct itself... Any suggestions for how I could do this?
Can anyone offer some help?
Here's the JS:
var listen = true;
function nextSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: $('#section1').scrollTop() + $(window).height()
});
}
function prevSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: -$('#section1').scrollTop() + $(window).height()
});
}
function showSlide(index)
{
var offset = $('#section1 div').eq(index).offset();
offset = offset.top;
if(offset){
listen = false;
$('.slide-dot').removeClass('active');
$('.slide-dot').eq(index).addClass('active');
$('#section1').stop(true,false).animate({
scrollTop: offset
}, 500, function(){
listen = true;
});
} else {
alert('error');
}
}
$(document).ready(function(){
var fullHeight = 0;
$('#section1 div').each(function(){
fullHeight = fullHeight + $(this).height();
});
var lastScrollTop1 = 0;
$('#section1').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
if( $('#section1').scrollTop() + $(window).height() == fullHeight) {
if(listen){
$('body').addClass('shifted');
}
}
}
lastScrollTop1 = st;
});
$('#section1').on('mousewheel', function(e){
e.preventDefault();
var st = $(this).scrollTop();
if (st > lastScrollTop1){
nextSlide();
} else {
prevSlide();
}
});
var lastScrollTop2 = 0;
$('#section2').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
} else {
if( st == 0 ){
$('body').removeClass('shifted');
}
}
lastScrollTop1 = st;
});
$('.slide-dots').css({'margin-top':-$('.slide-dots').height() / 2});
$('.slide-dot').first().addClass('active');
$(document).on('click', '.slide-dot', function(e){
e.preventDefault();
showSlide( $(this).index() );
});
$(document).on('click', '.slide-dot-fake', function(e){
e.preventDefault();
$('body').addClass('shifted');
});
});
And for those wondering why I'm not using something like fullPage.js, it's because it can't handle the way I want to transition between the two areas and have two scrollbars (one for each area).
You can use:
e.originalEvent.wheelDelta
instead of:
st > lastScrollTop1
in the mousewheel event for your third problem to check if the user has scrolled up or down. And also change the +/- in prevSlide. I used dm4web's fiddle for your first problem. And I used:
scrollTop: offset - 1
instead of:
scrollTop: offset
for your second problem, because when the scroll reaches to the last pixel of the third element, it automatically goes to the next section, so 1 pixel is enough for it not to.
Here's the fiddle: http://jsfiddle.net/3odc8zmx/3/
As suggested by #chdltest, you could do it by using fullPage.js.
Here's an example. Go to the last section.
Code used for the example:
Javascript
$('#fullpage').fullpage({
sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
scrollOverflow: true,
scrollBar: true,
afterLoad: function (anchor, index) {
//hiding the main scroll bar
if (index == 4) {
$('body, html').css('overflow', 'hidden');
}
//showing the main scroll bar
if (index == 3) {
$('body, html').css('overflow', 'visible');
}
}
});
CSS (in case you prefer to use the normal style for it)
/* Normal style scroll bar
* --------------------------------------- */
.slimScrollBar {
display: none !important;
}
.fp-scrollable {
overflow: auto !important;
}
Advantages of using fullPage.js instead to your own code:
Strongly tested in different devices and browsers. (IE, Opera, Safari, Chrome, Firefox..)
Prevent problems with trackpads, Apple laptops trackpads or Apple Magic Mouse.
Old browser's compatibility, such as IE 8, Opera 12...
Touch devices compatibility (IE Windows Phone, Android, Apple iOS, touch desktops...)
It provides many other useful options and callbacks.

Change cursor when div scrolls up or down

I have a div that implements Scriptperlative's CursorDivScroll script. How can I implement two customized cursors in the div that is using the script; one that shows when scrolling down and one that shows when scrolling up? Here is the javascript and HTML that I have thus far. The javascript is just the CursorDivScroll script.
<script type='text/javascript' >
$(document).ready(function() {
CursorDivScroll( 'repertoirescroll', 40, 40 ).noHorizontal();
});
</script>
#repertoirescroll {
cursor: url(../images/arrow.png), auto;
position:relative;
}
Thanks for any help in advance. I think I need to implement an if statement that says if mousemove = mousedown use this cursor else if mousemove = up use this cursor...? Not sure how to do this.
Checking if the scrollTop is decreasing or increasing should tell you if it's scrolling up or down, and then just set the cursor based on that when scrolling, and use a timeout to reset the cursor when scrolling stops :
var top=0, timer;
$(window).on('scroll', function() {
clearTimeout(timer);
var scrollTop = $(this).scrollTop(),
cursor = scrollTop > top ? 'pointer' : 'wait';
$('body').css('cursor', cursor);
top = scrollTop;
timer = setTimeout(function() {
$('body').css('cursor', 'default');
}, 500);
});​
FIDDLE

Categories

Resources