Imprecise values from scrollTop() depending on scroll speed - javascript

I am currently working on a Parallax Effect using jQuery. For that I am using a JS Class.
When I was first testing the code I thought everything was working fine. However I just found out that the parallax_container divs are behaving differently based on how fast the user is scolling. I am pretty sure that this happens because the window.scroll function just is not accurate enough to use it in this case. Thats why I changed the code and added the setInterval function the change the scrollTop Variable as often as possible, but this didn't change my problem.
Did I take the wrong approach, or is there a clever way to get the scroll Postion in a "linear" way no matter how fast the user scrolls ?
I added the part of the code that seems important to me, but i can post more if needed.
Codepen Example
jQuery(document).ready(function () {
jQuery("." + elemCssClass).addClass("parallax_container");
jQuery("." + elemCssClass).css("position", "relative");
jQuery(".parallax_container").each(function (index) {
jQuery(this).attr('id', 'parallax_' + (index + 1));
});
var lastScrollTop = 0;
var scrollDirect;
var initialTop = parseInt(jQuery("." + elemCssClass).css("top"));
var scr;
setInterval(function () {
scr = jQuery(window).scrollTop()
}, 0.00005);
jQuery(window).scroll(function () {
if (mediaQuery.matches) {
return;
}
if (scr > lastScrollTop) {
scrollDirect = "down"
} else {
scrollDirect = "up"
}
lastScrollTop = st;
var elem = document.querySelector("." + elemParentCssClass);
var visible = ctrl.isInViewport(elem);
if (visible) {
if (scr === 0) {
jQuery("." + elemCssClass).css('top', initialTop);
}
var diff = scr - initY;
var ratio = jQuery("." + elemCssClass).css('top');
// Hier wird der Speed der im VC eingestellt ist angewendet.
// Es wird gechekct ob nach oben oder unten gescrolled wird und entweder + oder - gerechnet
if (scrollDirect === "up") {
jQuery("." + elemCssClass).css({
top: "+=" + elemSpeed + 'px'
});
}
if (scrollDirect === "down") {
jQuery("." + elemCssClass).css({
top: "-=" + elemSpeed + 'px'
});
}
}
else {
jQuery("." + elemCssClass).css('top', 0);
}
var initY = jQuery("." + elemParentCssClass).offset().top
var height = jQuery("." + elemParentCssClass).height()
var endY = initY + jQuery("." + elemParentCssClass).height()
}) //window.scroll()
}) // document.ready()

Related

My script needs page refresh for it to run

Every time I load my page for the first time my script does not load, I need to refresh the page at least 3 times for it to run. How can I make my script run without a page refresh? This particular script is in BABEL.
'use strict';
var deg = 0;
var index = 0;
$('#' + index).css('opacity', '1');
$('.navbar').contextmenu(function () {
return false;
});
$('.navbar').on('mousewheel', function (e) {
var move = -60;
var nextIndex = nextIndex = (index + 1) % 6;
if (e.originalEvent.wheelDelta / 120 <= 0) {
// wheel up
move = 60;
nextIndex = index -1 < 0 ? 5 : index - 1;
}
$('.scroll-list').css('transform', 'rotateX(' + (deg + move) + 'deg)');
$('#' + index).css('opacity', '0.01');
$('#' + nextIndex).css('opacity', '1');
index = nextIndex;
deg = deg + move;
event.stopPropagation();
console.timeEnd('cache');
});
And what if you wrapped your code inside a window.onload function?
window.onload = function() {
// your code
}
Your code will only run when the html document is "ready" and fully loaded.
You are running Javascript that depends on page elements and the javascript is executed before the elements are on the page;
Wrapp all your code inside document.ready function
$(document).ready(function () {
var deg = 0;
var index = 0;
$('#' + index).css('opacity', '1');
$('.navbar').contextmenu(function () {
return false;
});
$('.navbar').on('mousewheel', function (e) {
var move = -60;
var nextIndex = nextIndex = (index + 1) % 6;
if (e.originalEvent.wheelDelta / 120 <= 0) {
// wheel up
move = 60;
nextIndex = index - 1 < 0 ? 5 : index - 1;
}
$('.scroll-list').css('transform', 'rotateX(' + (deg + move) + 'deg)');
$('#' + index).css('opacity', '0.01');
$('#' + nextIndex).css('opacity', '1');
index = nextIndex;
deg = deg + move;
event.stopPropagation();
console.timeEnd('cache');
});
});
Wrap your code in ready function, so that your JavaScript executes after DOM is loaded.

Function not starting when scroll point is over top of the div

I use a scrollTop function to start animations, delays, etc when the div is scrolled to. It works for other things on my page, but for some reason, this function is not working and it loads on page load.
Does anyone see anything wrong in my code? This can be seen live here:
<div class="blue-box-container">
</div>
$(function() {
var oTop = $('.blue-box-container').offset().top - window.innerHeight;
$(window).scroll(function() {
var pTop = $('body').scrollTop();
console.log(pTop + ' - ' + oTop);
if (pTop > oTop) {
blueBoxDelays();
}
});
});
$('.fadeBlock').css('display', 'none');
blueBoxDelays();
function blueBoxDelays() {
var delay = 0;
$('.fadeBlock').each(function(i) {
$(this).delay(400 + delay).fadeIn(1000);
delay = 200 * (i + 1);
});
};
I extracted your code to a fiddle and it works correctly https://jsfiddle.net/26jw7Low/3/, you just need to remove the call to blueBoxDelays() which is outside of the initial function as seen below.
$(function() {
var oTop = $('.blue-box-container').offset().top - window.innerHeight;
$(window).scroll(function() {
var pTop = $('body').scrollTop();
console.log(pTop + ' - ' + oTop);
if (pTop > oTop) {
blueBoxDelays();
}
});
});
$('.fadeBlock').css('display', 'none');
// REMOVE THIS blueBoxDelays();
function blueBoxDelays() {
var delay = 0;
$('.fadeBlock').each(function(i) {
$(this).delay(400 + delay).fadeIn(1000);
delay = 200 * (i + 1);
});
};
Function $('.fadeBlock').css('display', 'none'); maybe not yet execute
You can put it to $(function(){}) end try again:
$(function() {
$('.fadeBlock').css('display', 'none');
var oTop = $('.blue-box-container').offset().top - window.innerHeight;
$(window).scroll(function() {
var pTop = $('body').scrollTop();
console.log(pTop + ' - ' + oTop);
if (pTop > oTop) {
blueBoxDelays();
}
});
});

Smooth javascript navigation stops working after first click

This webpage http://www.eboxlab.net/ has a menu on the left side. What I need to achieve is to be able to go to a page section when the respective menu option is pressed. Here is my code (pretty sure it's quite bad, but I will clean it up later, after I make it work):
navigateMe();
navInit = 1;
navNext = 2;
function navigateMe() {
step = jQuery('ul#navigation li').size();
looper = setInterval(function(){
if(navNext > step + 1) {
navInit = 1;
navNext = 1;
}
var refLink = jQuery('ul#navigation li:nth-child(' + navInit + ') a').attr('href').replace('#', '');
var divLink = jQuery("div[id='" + refLink + "']").offset().top;
jQuery('ul#navigation li:nth-child(' + navInit + ') a').on('click', function() {
jQuery('html, body').animate({
scrollTop: divLink
}, 500);
});
navInit = navNext;
navNext = navNext + 1;
}, 0);
}
However the problem is that it only works once. After you click menu once, it doesn't slide up or down anymore. Please tell me what's wrong with it.
Many thanks in advance.

how to use setInterval to continue animation while mouse is over div

I am trying to modify a slideshow to continuously animate while the mouse is over the back or next arrow. If the mouse leaves, I would like the animation to stop where it is.
I found this post and this post which are helpful in telling me I need to use setInterval, but because I am a beginner I am not sure how to implement it with the code I have. I tried updating the miliseconds set in the counter variable but that didn't change anything.
Here is the hover code so far. It advances the image on hover but not continuously.
$(document).ready(function(){
var thumbs = $('ul.thumbHolder li');
var bigImgs = $('ul.imgHolder li');
var mask = $('.imgHolder');
var imgW = $('ul.imgHolder li').width();
var speed = 800;
thumbs.removeClass('selected').first().addClass('selected');
thumbs.click(function () {
var target = $(this).index();
mask.animate({
'left': '-' + imgW * target + 'px'
}, speed);
thumbs.removeClass('selected');
$(this).addClass('selected');
});
$('.Bleft').on('mouseover', function () {
var i = $('ul.thumbHolder li.selected').index();
i--;
$('ul.thumbHolder li.selected').removeClass('selected');
thumbs.eq(i).addClass('selected');
if (i === -1) {
mask.animate({
'left': '-' + imgW * $('ul.thumbHolder li').index() + 'px'
}, speed);
} else {
mask.animate({
'left': '-' + imgW * i + 'px'
}, speed);
}
clearInterval(counter);
});
$('.Bright').on('mouseover', function () {
var i = $('ul.thumbHolder li.selected').index();
i = i >= thumbs.length - 1 ? 0 : i + 1;
$('ul.thumbHolder li.selected').removeClass('selected');
thumbs.eq(i).addClass('selected');
mask.animate({
'left': '-' + imgW * i + 'px'
}, speed);
clearInterval(counter);
});
var count = 0;
var counter = window.setInterval(timer, 5000);
function timer() {
count = count + 0;
if (count >= 0) {
count = 0;
return;
}
mask.animate({
'left': '-' + imgW * count + 'px'
}, speed);
thumbs.removeClass('selected');
thumbs.eq(count).addClass('selected');
}
});
This is an example of what I am trying to achieve (I know it is flash but I think it can be done with jQuery too).
This is a fiddle that has all my work so far.
Thank you for any help.
I think I am close to the solution. This is my idea.
Every ul.imgHolder li is divided in many blocks of 20px ( you can change the size of course ), so if a div has a size of 980px you will have 49 blocks for image.
When mouseover event is fired I will slide for a block every speed milliseconds until the mouseout is fired.
I've implemented only the slide right button, I've deleted partially some logic, sorry!
var $ = jQuery.noConflict(true);
$(document).ready(function(){
var thumbs = $('ul.thumbHolder li');
var bigImgs = $('ul.imgHolder li');
var mask = $('.imgHolder');
var imgW = $('ul.imgHolder li').width(); //Assuming imgW % 20 = 0
var blockSize = 20; //20px
var blocksPerThumb = imgW/blockSize;
var numBlocks = (blocksPerThumb)*thumbs.length;
var speed = 400;
var blockPos = 0;
var currentAnim = null;
thumbs.removeClass('selected').first().addClass('selected');
thumbs.click(function () {
var target = $(this).index();
mask.animate({
'left': '-' + imgW * target + 'px'
}, speed,'linear');
thumbs.removeClass('selected');
$(this).addClass('selected');
});
$('.Bleft').on('mouseover', function () {
});
$('.Bright').on('mouseover', function(){
currentAnim = setInterval(goRight,speed);
}).mouseout(function(){
clearInterval(currentAnim);
});
var goRight = function () {
blockPos = (blockPos+1)%numBlocks;
mask.animate({
'left': '-' + blockSize * blockPos + 'px'
}, speed,'linear');
};
});
Good Work!

Get Mouse Position or Element Position

I am working on a tooltip plugin with the following options:
Mouse = True|False. Tooltip position relative to Mouse or Element;
Static = True|False. Follow mouse when option Mouse = true.
I have a JSFiddle example in: http://jsfiddle.net/mdmoura/RPUX6/
THE PROBLEM:
When I place the mouse over the last tooltips of the list the position is wrong.
This happens every time I have scrolled the page ... I have no idea why.
The part of the code which sets the position is:
$(this).each(function (e) {
// SOME CODE
$this.mouseenter(function (e) {
var $tooltip =
$("<div>")
.attr("class", options.class)
.html(options.content !== '' ? (typeof options.content === 'string' ? options.content : options.content($this, $tooltip)) : tooltip.title)
.appendTo('body');
$this.attr('title', '');
var position = [0, 0];
if (options.mouse) {
position = [e.clientX + options.offset[0], e.clientY + options.offset[1]];
} else {
var coordinates = $this[0].getBoundingClientRect();
position = [
(function () {
if (options.offset[0] < 0)
return coordinates.left - Math.abs(options.offset[0]) - $tooltip.outerWidth();
else if (options.offset[0] === 0)
return coordinates.left - (($tooltip.outerWidth() - $this.outerWidth()) / 2);
else
return coordinates.left + $this.outerWidth() + options.offset[0];
})(),
(function () {
if (options.offset[1] < 0)
return coordinates.top - Math.abs(options.offset[1]) - $tooltip.outerHeight();
else if (options.offset[1] === 0)
return coordinates.top - (($tooltip.outerHeight() - $this.outerHeight()) / 2);
else
return coordinates.top + $this.outerHeight() + options.offset[1];
})()
];
}
$tooltip.css({ left: position[0] + 'px', top: position[1] + 'px' });
You can also see the code and the demo in http://jsfiddle.net/mdmoura/RPUX6/.
Thank You!
You need to account for scrollTop and scrollLeft of the window.
Basic idea:
var win = $(window);
$tooltip.css( {
left: position[0] + win.scrollLeft() + 'px',
top: position[1] + win.scrollTop() + 'px'
});
Add scrollTop by
document.body.scrollTop
And you will be good to go..
In your code make these changes
function () {
if (options.offset[1] < 0)
return coordinates.top - Math.abs(options.offset[1]) - $tooltip.outerHeight()+document.body.scrollTop;
else if (options.offset[1] === 0)
return coordinates.top - (($tooltip.outerHeight() - $this.outerHeight()) / 2)+document.body.scrollTop;
else
return coordinates.top + $this.outerHeight() + options.offset[1]+document.body.scrollTop;
})

Categories

Resources