I'm trying to get an overlay div's opacity to fade to black as you approach a targeted element in the middle of the page, and then fade back to transparent after that element exits the viewport.
(Broken) Example: https://jsfiddle.net/dtcgbxcn/3/
As you approach the 'blue' section, it should get darker. The page should be solid black before the blue section enters the viewport. Then, after the blue section exits the viewport, it begins to gradually fade out the opacity. By the time you reach the bottom of the page (or another targeted element), the overlay should be fully transparent again.
Note that, due to responsiveness, the height of any of these sections is indeterminate.
$(window).on('scroll', function() {
var st = $(this).scrollTop(),
offset = $('.blue').offset().top - $('.blue').height(),
opacity = st / offset;
_docHeight = $('.red').height() + $('.blue').height() + $('.yellow').height();
$('.overlay').height(_docHeight);
if (opacity > 2) {
opacity = 3 - opacity;
}
$('.overlay').css('opacity', opacity);
});
I have fiddled around with your example, Hopefully this is what you were looking for as far as functionality. It should be 100 opacity right before the blue appears, and 100% clear as the blue comes off the screen. I would prob warp this whole thing in a closure, and cache the selectors so you don't have to call $() every time, but other than that - this should work.
Your fiddle was a little different than your example above - but let me know if this is what you are looking for.
https://jsfiddle.net/gmydzzmf/1/
$(window).on('scroll', function() {
var st = $(this).scrollTop(),
win_height = $(window).height(),
offset = $('.two').offset().top - $('.two').height() - ( win_height / 2),
_docHeight = $('.one').height() + $('.two').height();
if (st<offset ){
// fading in
opacity = st/offset;
} else {
// fading out
opacity = ((_docHeight - st)/(win_height*2));
}
$('.overlay').height(_docHeight); //move this to resize event
$('.overlay').css('opacity', opacity);
});
Related
Case:
I have a slider that scrolls through some images, while, when you scroll down, the menu and content moves over it. Once the menu gets to the top, it sticks to it, as it's changed to a fixed position.
Problem:
Once the menu snaps to place, it resets it's original position (a margin-top) from a generated ammount of pixels to the 0 value. This cases the page to jump that generated ammount of pixels down, which shouldn't happen. It shouldn't jump down at all, but I think it has to do with the ammount of pixels that is generated before it is set to 0, which cases on my screen a gap of 955 pixels. It jumps thus 955 pixels down after it applies the fixed state.
So my questio now is, how can i fix this. I tried applying instead of a margin a padding (no go, white screen), applying instead of a margin-top: 0px a top:0 so i dont have to use the margins, but also a no go.
Case link:
http://test.thewebfanatics.com/jellyweb/home
Code
$(window).scroll(function () {
if ($('.resolutionwrap').length == 1) {
var documentScrollTop = $(document).scrollTop() + 100;
var fixedToggle = $('#slides').height();
if (documentScrollTop > fixedToggle) {
$('#hoofdmenu').addClass('fixed');
$('#hoofdmenu').css("margin-top", "0px");
} else {
$('#hoofdmenu').removeClass('fixed');
$('#hoofdmenu').css("margin-top", $('#slides').height() - 100);
}
}
});
Hope someone can help me on this matter.
Okay, as I was posting the remark on the fiddle, I realized that if the content moved, I could also just simply return it to it's position by javascript by making a counter balanced value of it.
Shortly said: I countered the margin, by creating a different margin-top that balanced that scale. It's maybe not the most beautifull solution, but it did the trick.
$(window).scroll(function () {
if ($('.resolutionwrap').length == 1) {
var documentScrollTop = $(document).scrollTop() + 100;
var fixedToggle = $('#slides').height();
// console.log($('#slides').height());
// console.log($('.resolutionwrap').height());
if (documentScrollTop > fixedToggle) {
$('#hoofdmenu').addClass('fixed');
$('#hoofdmenu').css("margin-top", "0px");
$('.content').css("margin-top", $('#slides').height());
} else {
$('#hoofdmenu').removeClass('fixed');
$('#hoofdmenu').css("margin-top", $('#slides').height() - 100);
$('.content').css("margin-top", "0px");
}
}
})
The code:
http://codepen.io/anon/pen/EjrpMM
So, i'm working on an interesting problem. I am working with a 2000px HTML document, that has a modal placed ontop of it.
The width of the div lightbox is 80%, and it's sitting positioned fixed.
The goal is, when scrolling down the page, to control the width of the div based on the scroll position. At the bottom of the page, it's only a third in size.
I've had trouble figuring out the proper equation or formula for this, and was seeking help.
Currently, I've been trying to look at the window.pageYOffset, to add 2.5% to the div while increasing, and minus 2.5% when scrolling back up, to bring it back to it's 80% width.
However, something isn't working right. I was seeing if the community had any ideas to help solve the problem.
I'm not using any frameworks for this.
Here's my javascript:
var lightBox = document.getElementById('lightBox'),
count = 80,
num = window.pageYOffset;
document.addEventListener('scroll', function(e) {
var offset = window.pageYOffset;
num >= offset ? count += 2.5 : count -= 2.5;
num = offset;
lightBox.style.width = count + '%';
});
View the code here, in this codepen
http://codepen.io/anon/pen/EjrpMM
Thank you!
You just have to change
+= 2.5 and -=2.5 to += 0.7 and -= 0.7
When I checked your code I did this and it worked.
Scroll event fired once on scroll independently on how much you've scrolled. E.g. if you've scrolled 1px scrollbar, or scrolled 100px using mousewheel scroll event will be fired once.
So if you need stable results you will need to calculate your div width depending on scroll position (window.pageYOffset).
Check this codepen fork. I've assumed that in the end of page div width should be 50%.
Core part is:
var lightBox = document.getElementById('lightBox');
var upperBound = 80;
var lowerBound = 50;
var tickValue = (upperBound - lowerBound) / window.innerHeight;
document.addEventListener('scroll', function(e) {
var offset = window.pageYOffset;
var count = upperBound - offset * tickValue;
lightBox.style.width = count + '%';
});
Important note: for crossbrowser way to get innerHeight you can check this answer
This is a simple equation. Let f : scroll |-> f(scroll) be the function that gives you the width of your div. You want f(0) = 0.8, f(2000)= 1/3.
Let's say you want the progression to be linear so f(scroll) = a*scroll + b, you can easily deduce that b = 0.8 and a = (1/3 - 0.8)/2000 = -0.000233. Now for any scroll value, you can find the width of your div.
Now you can change the values when you want, f(scroll) = (minWidth-maxWidth)/pageLength * scroll + maxWidth.
I am coding my page so that the content fades in and out as you scroll.
when you scroll away from the "trilogy" section, then scroll back up, it is not 100% opacity when at the top again.
Also the content fades out half way the trilogy section, then fades back in again. I need the content when at the top (minus the green header area) to be 100% opacity when in view.
Code:
$(document).ready(function() {
$(window).bind('scroll', function(e) {
setParalaxContent();
});
function setParalaxContent() {
var trilogy = {
scrollTop: $(window).scrollTop(),
windowHeight: $(window).height(),
contentTop: $('.trilogy2').position().top,
contentHeight:2200
};
// determine scrollTop's bounds where content enters & exits the window
trilogy.lowerBound = trilogy.contentTop - trilogy.windowHeight;
trilogy.upperBound = trilogy.contentTop + trilogy.contentHeight;
// determine scrollTop's position percentage (x2) in relation to bounds
trilogy.percent = (trilogy.scrollTop - trilogy.lowerBound) / (trilogy.upperBound - trilogy.lowerBound) * 2;
}
$('.trilogy2').animate({
opacity: 1 - Math.abs(trilogy.percent - 1)
}, 1);
Please see full code at:
http://jsfiddle.net/warrior_76/pnr4fdyg/
I'm trying to fade in an element based off when it first enters the viewport then have it equal 100% opacity by the time it hits the end of the viewport. I have working as far as reaching 100% opacity when it gets to the end. However, when it starts animating, it starts out at about 60% which I know is because I am basing it off the scroll position. So my question is how can I calculate the opacity starting at 0 once it enters the viewport?
This is what I have so far:
$('.left-cont').each(function() {
var $this = $(this),
leftPos = $this.offset().left,
fadeStart = leftPos - winWidth,
fadeUntil = leftPos,
opacity;
console.log( winWidth - (leftPos - scrollPos));
console.log(fadeStart);
if( scrollPos <= fadeStart ) {
opacity = 0;
}
else {
opacity = scrollPos/fadeUntil;
}
$this.css({
'opacity': opacity
});
});
I can provide more context if needed. Any help is appreciated.
1) Is this jQuery function only executed once or is it placed inside the onScroll-binded function?
$( window ).scroll(function() {
/* get scroll top and left values here */
$( ".box" ).each(function(){
/* do position check and css adjustments here */
});
});
2) The calculation for the opacity is:
(1 - ((box_offsetTop - scrollTop) / windowHeight))
3) I made a working example here for scrolling vertically: http://jsfiddle.net/0mks8eut/1/
You can change it to calculate opacity based on horizontal scrolling by (un)commenting the other calculation inside the function.
! Make sure that there is enough content (or padding/margin) after/next to the object. Otherwise it will never reach opacity:1 (e.g. the top/left of the screen).
So I have an object on a page with a background image and on mousemove it moves the background position relative to the mouse. But the only problem i have is animating the background image to the current position of the mouse when it enters the object.
I am able to animate the background position back to its original position.
Heres my jQuery
//MOUSE MOVE, INVERT BACKGROUND POSITION
jQuery('.homeSlider').mousemove(function(move){
var moveMouse = (move.pageX * -1 / 15);
jQuery('.homeSlider .slide').css({
'background-position-x': moveMouse + 'px'
});
});
//MOUSE LEAVE, ANIMATE BACKGROUND TO START POSITION
jQuery('.homeSlider').mouseleave(function(){
jQuery('.homeSlider .slide').animate({
'background-position-x': '0'
});
});
http://jsfiddle.net/TWHh2/
Add this CSS
.slide {
transition: background-position-x 0.5s;
}
updated fiddle
In addition to using CSS transitions as vals suggested, you could also use JS to either set the position or animate it depending on the distance it needs to be moved. If the distance is above a threshold, you can animate it (otherwise the movement is jumpy). Otherwise, set the CSS as you currently are.
Something like this may work:
var animating = false;
jQuery('.homeSlider').mousemove(function(move){
var $slider = jQuery('.homeSlider .slide');
var moveMouse = (move.pageX * -1 / 3);
var bgPos = $slider.css('background-position-x');
if (!animating && Math.abs(moveMouse - parseInt(bgPos)) > 10) {
animating = true;
$slider.animate({
'background-position-x': moveMouse + 'px'
}, 400);
setTimeout(function() {
animating = false;
}, 400);
} else if (!animating) {
$slider.css({
'background-position-x': moveMouse + 'px'
});
}
});
jsFiddle
I would recommend this over the pure CSS solution because that would always apply the animation, which includes small background position changes. If you check the fiddle with the transition, the smooth background effect is no longer very responsive and loses some of its smoothness.
The downside to this is that it becomes poorly-responsive when the mouse moves quickly, similar to the CSS-only solution.
Alternative
Combine the JS and CSS transition solutions:
CSS
.slide.animate {
transition: background-position-x 0.4s;
}
JS
...
if (!$slider.hasClass('animate') && Math.abs(moveMouse - parseInt(bgPos)) > 10) {
$slider.addClass('animate');
setTimeout(function() {
$slider.removeClass('animate');
}, 400);
}
...