Window scroll function lag - javascript

I have a function that positions a div depending on the webpages position.
function calcNav(){
var b = $('#breadcrumb').offset().top;
var w = $(window).scrollTop();
var x = b - w;
//console.log('breadcrumb from top = ' + b + ' window scrolled = ' + w + ' position of nav = ' + x);
$('.sub-nav').css('top', x);
}
calcNav();
$(window).scroll(calcNav);
The function works great, my only issue is that as its constantly rendering my page speed appears a bit laggy - is there any way I can run the function at the end of the scroll instead of during?

I would recommend to you use it with combination with setTimeout and add small amount of milliseconds:
var scrollTimeout;
$(window).scroll(function() {
clearTimeout( scrollTimeout );
scrollTimeout = setTimeout( calcNav, 50 );
});
clearTimeout in this case is used to not trigger previous call if next scroll event was triggered less than 50ms, in case you think your users will scroll slower you can increase this value for example to 100ms etc.

Related

Move element on page as user scrolls up and down

I am struggling to achieve what should be a simple task.
Page Loads
User freely scrolls down through different sections.
When a specific DIV reaches the centre of the page I would like to pause/prevent scrolling down until the DIV has been moved horizontally across to the left a fixed number of pixels.
Then the user can be allowed to continue scrolling down the page.
Also, I would like to achieve the opposite effect if the user scrolls up i.e. scroll the div to the right a fixed number of pixels before continuing up.
Below is a sample of my code.
$(window).scroll(function() {
sD = $(this).scrollTop();
// $('.features-2-item').width();
if (sD > (f2Pos.top + 100) && sD < f2Pos.top + 2000 + 100) {
// if scroll distance is greater than the top position of
// the statements when they are centred in the viewport,
// and less than the top position of statements centred
// plus the height of 4 statements, prevent user from
// scrolling, then run function to change statements.
sD = f2Pos.top + 100;
var scroll = $(window).scrollTop();
// console.log(('up or down: ' + xSlide + ' > - ' + statementWidth + ' || ' + scroll + ' < ' + position));
if (xSlide > -statementWidth || scroll < position) {
slideStatements();
}
}
if (sD > f2Pos.top + 2000) {
// if scroll distance is greater than the top positon of
// the statements, centred in the viewport, plus the
// height of 4 statements, the user has scrolled through
// all of the statements and should be allowed to resume
// scrolling. Scrolling should be adjusted to take away
// the distance equal to the height of 4 statements.
sD = sD - 2000 + 100;
}
});
var statementWidth = $('.features-2-item').width();
var xSlide = statementWidth;
var position = $(window).scrollTop();
function slideStatements() {
var st = $(this).scrollTop();
if (st > lST) {
// Going Down
if (cS) {
// disallow scrolling until after statement slides
cS = false;
xSlide = Math.floor(xSlide + 32);
$(window).one('scroll.slideStatements', function() {
$(".features-2-container").css("transform", "translateX(" + xSlide + "px)");
});
// allow scrolling after statement slides
cS = true;
}
} else {
// Going Up
if (cS) {
// disallow scrolling until after statement slides
cS = false;
xSlide = Math.floor(xSlide - 32);
$(window).one('scroll.slideStatements', function() {
// $sS.slick("slickPrev");
$(".features-2-container").css("transform", "translateX(" + xSlide + "px)");
});
// allow scrolling after statement slides
cS = true;
}
}
lST = st - 1;
}
Any suggestion swould be great.
regards
Hi I'm not an expert here but I would like to share my method.
In my opinion the hardest part is how to prevent the scrolling. So we are not going to prevent it, instead we are going to take some advantage of it.
Let's say we have 3 sections like
<section>...</section>
<section class='stuart'>
<div class='kevin'></div>
</section>
<section>...</section>
And style like
.stuart {
height: 600px;
}
.kevin {
position: absolute;
width: 50px;
height: 50px;
background: tomato;
}
So stuart is a our container and kevin is a box inside.
Our goal is simple, when kevin goes up and pass the middle of window we will keep it at that middle (vertical) and move it from left to right (horizontal) until the end of stuart pass.
Code will be like
if (stuart.top < windowHeight / 2 &&
stuart.top + stuart.height - kevin.height > windowHeight / 2) {
let distance = windowHeight / 2 - stuart.top
kevin.classList.add('fixed')
kevin.style.left = distance + 'px'
}
The important part is the distance which always relate to the position of stuart, so you will no need to do anything about opposite effect.
Final example here.
Bad news, you need to calculate the height of container by yourself or a fixed position may not work in your case or other things but I hope this idea will help you in some way. Thanks.

Using animate.css (link in description) how do I trigger an animation when a particular event is finished

I have an an image moving across the screen and out of viewport, when the image reaches a particular absolute position (right: - 200), I want to trigger the below animation. I am relatively new to programming, not sure how to track when a particular function is done so that I can trigger the below animation.
var $startLessonButton = $('.startLessonButtonUp');
$startLessonButton.mouseup(function() {
$(this).addClass('animated slideInLeft');
});
---------
var movingOutAnimationCounter = 2;
var movingOutCurrentPosition = window.innerWidth / 2 - 200
function moveTrumpOut() {
movingOutCurrentPosition -= 2;
trumpyWrapper.style.right = movingOutCurrentPosition + 'px';
if (movingOutAnimationCounter < 9 ) {
trumpy.src = '../images/trump_walking_out_' + movingOutAnimationCounter + '.png';
movingOutAnimationCounter += 1;
} else {
movingOutAnimationCounter = 1;
trumpy.src = '../images/trump_walking_out_' + movingOutAnimationCounter + '.png';
}
if (movingOutCurrentPosition > -200 ) {
requestAnimationFrame(moveTrumpOut);
}
}
All the best!
If you know time, when moving element is hidden, you can use this function:
setTimeout(function(){ $('.elem').addClass("animCssClass") }, 1000);
Last parameter, in this example: 1000 is time in ms, when function inside should execute. Run this function on mouseup when you adding class to moving element.

How to check bottom of child div touching parent bottom

i'm trying to change position of a child element(with varying height based on text) using range input,i would like to stop applying top position once the child div touches the bottom of the parent having fixed height.
$('#change_position').on('input', function () {
var val = +$(this).val(),
ScrSize = parseInt($('.screen').css('height')),
Stop = $('.screentip').offset().top,
h = parseInt($('.screentip').css('height')),
tofsset = Stop - h;
if (tofsset < ScrSize) {
$('.screentip').css('top', val + "%");
}
});
The height you are expecting jQuery to return is actually a string with the ending "px". You can use the function .height(). This will return you the height of the element as integer. I have tried a slightly modiefied version of your code:
$('#input').on('input', function () {
var val = parseInt($(this).val()),
ScrSize = parseInt($('#container').height()),
TxtSize = parseInt($("#text").height()),
Stop = ScrSize - TxtSize,
valInPixel = ScrSize * val / 100;
if (valInPixel < Stop) {
$('#text').css('top', val + "%");
}
else
{
$("#text").css("top", Stop + "px");
}
});
The else part will position your element to the bottom, if the number exceeds the frame. You may also have to be aware of padding and margin. This could also lead to mispositioning.
Hope this helps.

How to determine if vertical scroll bar has reached the bottom of the web page?

The same question is answered in jQUery but I'm looking for solution without jQuery.
How do you know the scroll bar has reached bottom of a page
I would like to know how I can determine whether vertical scrollbar has reached the bottom of the web page.
I am using Firefox3.6
I wrote simple Javascript loop to scroll down by 200 pixel and when the scroll bar reached the bottom of the page, I want to stop the loop.
The problem is scrollHeight() is returning 1989.
And inside loop scrollTop is incremented by 200 per iteration.
200 ==> 400 ==> 600 .... 1715
And from 1715, it won't increment so this loop continues forever.
Looks like scrollHeight() and scrollTop() is not right way to compare in order to determine the actual position of scrollbar? How can I know when the loop should stop?
code:
var curWindow = selenium.browserbot.getCurrentWindow();
var scrollTop = curWindow.document.body.scrollTop;
alert('scrollHeight==>' + curWindow.document.body.scrollHeight);
while(curWindow.document.body.scrollHeight > curWindow.document.body.scrollTop) {
scrollTop = curWindow.document.body.scrollTop;
if(scrollTop == 0) {
if(window.pageYOffset) { //firefox
alert('firefox');
scrollTop = window.pageYOffset;
}
else { //IE
alert('IE');
scrollTop = (curWindow.document.body.parentElement) ? curWindow.document.body.parentElement.scrollTop : 0;
}
} //end outer if
alert('current scrollTop ==> ' + scrollTop);
alert('take a shot here');
selenium.browserbot.getCurrentWindow().scrollBy(0,200);
} //end while
When you tell an element to scroll, if its scrollTop (or whatever appropriate property) doesn't change, then can't you assume that it has scrolled as far as is capable?
So you can keep track of the old scrollTop, tell it to scroll some, and then check to see if it really did it:
function scroller() {
var old = someElem.scrollTop;
someElem.scrollTop += 200;
if (someElem.scrollTop > old) {
// we still have some scrolling to do...
} else {
// we have reached rock bottom
}
}
I just read through the jQuery source code, and it looks like you'll need the "pageYOffset". Then you can get the window height and document height.
Something like this:
var yLeftToGo = document.height - (window.pageYOffset + window.innerHeight);
If yLeftToGo is 0, then you're at the bottom. At least that's the general idea.
The correct way to check if you reached the bottom of the page is this:
Get document.body.clientHeight = the height of the ACTUAL screen shown
Get document.body.offsetHeight or document.body.scrollHeight = the height of the entire page shown
Check if document.body.scrollTop = document.body.scrollHeight - document.body.clientHeight
If 3 is true, you reached the bottom of the page
function scrollHandler(theElement){
if((theElement.scrollHeight - theElement.scrollTop) + "px" == theElement.style.height)
alert("Bottom");
}
For the HTML element (like div) add the event -- onscroll='scrollHandler(this)'.
Here is some code I've used to power infinite scrolling list views:
var isBelowBuffer = false; // Flag to prevent actions from firing multiple times
$(window).scroll(function() {
// Anytime user scrolls to the bottom
if (isScrolledToBottom(30) === true) {
if (isBelowBuffer === false) {
// ... do something
}
isBelowBuffer = true;
} else {
isBelowBuffer = false;
}
});
function isScrolledToBottom(buffer) {
var pageHeight = document.body.scrollHeight;
// NOTE: IE and the other browsers handle scrollTop and pageYOffset differently
var pagePosition = document.body.offsetHeight + Math.max(parseInt(document.body.scrollTop), parseInt(window.pageYOffset - 1));
buffer = buffer || 0;
console.log(pagePosition + "px / " + (pageHeight) + "px");
return pagePosition >= (pageHeight - buffer);
}
<span id="add"></add>
<script>
window.onscroll = scroll;
function scroll () {
if (window.pageYOffset + window.innerHeight >= document.body.scrollHeight - 100) {
document.getElementById("add").innerHTML += 'test<br />test<br />test<br />test<br />test<br />';
}
}
</script>

Javascript-moving image

How is it posible move an image from one position to other with fadeout?
I hav such functions
for hiding:
function SetOpacity(object,opacityPct)
{
// IE.
object.style.filter = 'alpha(opacity=' + opacityPct + ')';
// Old mozilla and firefox
object.style.MozOpacity = opacityPct/100;
// Everything else.
object.style.opacity = opacityPct/100;
}
function ChangeOpacity(id,msDuration,msStart,fromO,toO)
{
var element=document.getElementById(id);
var opacity = element.style.opacity * 100;
var msNow = (new Date()).getTime();
opacity = fromO + (toO - fromO) * (msNow - msStart) / msDuration;
if (opacity<0)
SetOpacity(element,0)
else if (opacity>100)
SetOpacity(element,100)
else
{
SetOpacity(element,opacity);
element.timer = window.setTimeout("ChangeOpacity('" + id + "'," + msDuration + "," + msStart + "," + fromO + "," + toO + ")",1);
}
}
function FadeOut(id)
{
var element=document.getElementById(id);
if (element.timer) window.clearTimeout(element.timer);
var startMS = (new Date()).getTime();
element.timer = window.setTimeout("ChangeOpacity('" + id + "',500," + startMS + ",100,0)",1);
}
for get current position or next position (by id of image and id of div)
function findPos(e){
var obj = document.getElementById(e);
var posX = obj.offsetLeft;var posY = obj.offsetTop;
while(obj.offsetParent){
posX=posX+obj.offsetParent.offsetLeft;
posY=posY+obj.offsetParent.offsetTop;
if(obj==document.getElementsByTagName('body')[0]){break}
else{obj=obj.offsetParent;}
}
alert(posX+'-'+posY);
}
the first position is position of image, and next - is position of div
The easiest approach with minimal code will be to use jQuery and use the animate function mate.
Ex:
$(".block").animate({"left": "+=50px"}, "slow");
You can use multiple parameters in the brackets like background-color, opacity, etc as you wish to dynamically change the values.
A link for your reference is located at: http://api.jquery.com/animate/
Most javascript animations rely on timer to create the effect of fluid motion. To slide an image across the page, you would set an interval that changed the css position to the right 1px every 5 milliseconds or something of the like. Javascript animation tutorial.
However, animation is most easily accomplished with a library like jquery or many others.

Categories

Resources