Jumping Elements - javascript

I'm creating a parallax effect and I've made it so that (almost) every element has a different scroll speed.
I've also made it so that elements down the page don't trigger their scroll speed until they've reached the viewport.
Here's the JS for trigger commands on reveal:
function isElementInViewport (el) {
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.bottom >= 0 &&
rect.left >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
My scroll speed code is:
$(window).scroll(function(){
var wScroll = $(this).scrollTop();
if (isElementInViewport($('#computer'))) {
$('#computer').css({
transform' : 'translate(0px, '+ wScroll /12 +'%)'
});
}
OR for elements already at the top of page:
$(window).scroll(function(){
var wScroll = $(this).scrollTop();
$('#shape-2').css({
'transform' : 'translate(0px, -'+ wScroll /8 +'%)'
});
The issue here is that when I add function isElementInViewport to the scroll speed.
It makes the element jump out of view when revealed, THEN it scrolls how I want it.
So, then it's out of place with the layout of the page.
I've tried compensating it by changing the position of the element so that when it's revealed it jumps to its original spot then starts scrolling, but this didn't prove helpful since the position varied from different screen sizes and resolutions.
Any way I can make it so it doesn't jump when revealed?

Make sure your base CSS declares a translation transform of zero, or add it from script before the element is in view; adding the attribute later may be causing the jump.

Related

How do I remove/disable the scrollTop function with JavaScript / jQuery?

I'm trying to write a script that has several variable and functions. The script is for a navbar and it should do the following:
On scroll:change bg from transparent to solid, and change logo img.
On small screens:change bg from transparent to solid, and change logo img.
The problem is that I can get it to work with one or the other but not both.
What happens is the resize works on small screen UNTIL you scroll down and back up. When it hits the top it the background goes back to transparent.
Is there a way to remove the scrollTop function on smaller screens? I feel like removing/disabling this function would fix the problem.
*** Is there a way to do something like this? ***
if (width < 786) {
//REMOVE scrollTop;//?
}
I'm just trying to figure out how to remove the scrollTop function if the screen is small.
I have tried placing the functions in separate scripts, and also using #media css, which comes the closest to working so far, but the "green" logo disappears when scroll hits top.
$(document).ready(function() {
$(window).scroll(function() {
$(window).resize(function() {
var height = $('.first-container').height();
var scrollTop = $(window).scrollTop();
var width = $(window).width();
if (scrollTop >= 0 || width < 768) {
$('.nav-container').addClass('solid-nav') &&
$('.navbar-brand img').attr('src','images/new-green-sm.png');
} else {
$('.nav-container').removeClass('solid-nav') &&
$('.navbar-brand img').attr('src','images/new-white-sm.png');
}
});
});
});
Just run this when you want to test the width to remove the function.
if (width < 768) {
scrollTop = function(){};
};
You could just always set scrollTop to 0 if width < 768 instead of calling the scrollTop method :
$(document).ready(function() {
$(window).scroll(function() {
$(window).resize(function() {
var height = $('.first-container').height();
var width = $(window).width();
// Set scrollTop always to 0 if width < 768
var scrollTop = (width < 768) ? 0 : $(window).scrollTop();
if (scrollTop >= 0 || width < 768) {
$('.nav-container').addClass('solid-nav') &&
$('.navbar-brand img').attr('src','images/new-green-sm.png');
} else {
$('.nav-container').removeClass('solid-nav') &&
$('.navbar-brand img').attr('src','images/new-white-sm.png');
}
});
});
});
This way if will never execute the second part of your if-statement if width < 768, no matter what the value of scrollTop is.

Transition and Animation for Horizontal website

I am creating a horizontal website. And i want to apply the transitions and animations to the elements when they display on the screen. But now, at the loading of the page itself all the transitions and animations are applying for all elements. I tried (:visible) but it didn't work. So please guide me how to apply transition to elements when they display on screen.
Thanks in advance.
Check whether DOM element is visible in current viewport or not.
function isElementInViewport(el) {
var rect = el.getBoundingClientRect();
if(rect.width!=0&&rect.height!=0&&$('#timeline').is(":visible")) {
return (
rect.top > 0 &&
rect.left > 0 &&
rect.bottom < (window.innerHeight || document.documentElement.clientHeight) &&
rect.right < (window.innerWidth || document.documentElement.clientWidth)
);
}else{
return false;
}
}
pass HTMLElement as an argument to this function and it will return whether it is visible in the current viewport or not.
Fire events to recheck the condition
window.addEventListener("load", function-tocheck-viewport-visibility);
window.addEventListener("resize", function-tocheck-viewport-visibility);
window.addEventListener("scroll", function-tocheck-viewport-visibility);

Using Jquery to find HTML element / content which occupies pixel position on page

I'm looking to find the HTML element or content which occupies the pixel position on a page. I am using currently using jQuery to find the scrollTop() position:
$(window).scroll(function (event) {
var scroll = $(window).scrollTop();
console.log(scroll);
// Do something
});
to understand the $(window).scrollTop() position, but I'd like to know what occupies the space. E.g., if a user scrolls to '300', what HTML element or content is there?
Scrolltop code from How to detect scroll position of page using jQuery
function checkElement(el){
var windowHeight = $(window).height();
var scroll = $(window).scrollTop();
var elementPosition = el.height() + el.position().top;
if (elementPosition > scroll && elementPosition < windowHeight + scroll){
return true;
}
return false;
}

ScrollLeft ScrollTop, How do they work?

I'm trying to make some of my element fixed for vertical and horizontal scrolling and looked up some examples on stackoverflow but I could not figure out why they work, therefore I cannot use it for a different purpose:
This is the code that everybody gives, and it works:
$(window).scroll(function() {
$('#header').css({
'top': $(this).scrollTop() + 15,
'left': $(this).scrollLeft() + 15 // top, left = 15px in css
});
}
So what it is doing is set the position of top and left of the header id tag so everytime window is scrolled, it goes to the position relative to window?
$(this).scrollTop() always print out 0 in my test however, if I do the below instead, it stop working:
function test() { /* Original code example, keeping this unmodified so some answers doesn't seem strange */
$('#header').css({
'top': 15,
'left': 15 // hardcode 15 just for example
});
}
What is the purpose of $(this).scrollTop() here that makes or breaks the functionality?
Lastly, I'm not allowed to use JQuery so I use javascript and none of these variations are working. Could you tell me what I'm doing wrong?
function test() {
var header = getElementById('header');
header.style.top = header.scrollTop + 15;
header.style.left = header.scrollLeft + 15;
}
also tried few others such as: using '15px', 15 + 'px'.
edit: modified first code example to the correct original code from stackoverflow
The getElementById function is not global on its own -- it is under the global document object. So you must use var header = document.getElementById('header');
Next, the browser's native scrollTop and scrollLeft functions used on a DOM element will tell you the scroll inside that element. For instance, for scrollTop is the measurement from the top of the element (which may be hidden because of scroll) to the top visible edge (In other words, it is the distance above the visible part of the element -- the part that's been hidden because of internal scrolling). If the top of the header element is always completely visible (and the header doesn't have it's own scrollbar), then this distance will always be zero.
To position the header relative to the scroll of the browser window, you may want to get the pageYOffset and pageXOffset on the window element instead, and then position the header based on that. For instance, window.pageYOffset + 15.
Here is a safer alternative that checks various possible places for the page's scroll (helps with browser compatibility).
var scrollTop = function(){
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
var scrollLeft = function(){
return (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
}
The last thing is that element.style.top should be given a string value that is like "10px", so you will need to do the calculation first and then add + 'px' at the end.
eg. header.style.top = window.scrollTop + 15 + "px";
Putting that all together:
var scrollTop = function(){
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
var scrollLeft = function(){
return (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
}
function test() {
var header = document.getElementById('header');
header.style.top = scrollTop() + 15 + 'px';
header.style.left = scrollLeft() + 15 + 'px';
}
Good luck! Hope that helps!
top and left property of css not going to work in this condition if you do not
add position property ..
function test() {
$('#header').css({
'position':'absolute',
'top': $(this).scrollTop() + 215,
'left': $(this).scrollLeft() + 15 // top, left = 15px in css
});
}
LIVE http://jsfiddle.net/mailmerohit5/t45ktx4r/

How to check if an element is in the view of the user with jquery

I have a very big draggable div in my window. This div has a smaller window.
<div id="draggable-area" style="width:500px;height:500px;overflow:hidden">
<div id="draggable" style="width:5000px;height:5000px">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
....
</ul>
</div>
</div>
How can I know if the li element is visible in the user viewport (I mean really visible, not in the overflow area)?
To check if an element is in the current veiwport:
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth)
);
}
(Source)
For a more robust method, I'd recommend Viewport Selectors, which allow you to just do:
$("#elem:in-viewport")
have a look at this plugin
It give's you the option to do the following selectors
$(":in-viewport")
$(":below-the-fold")
$(":above-the-top")
$(":left-of-screen")
$(":right-of-screen")
https://github.com/sakabako/scrollMonitor
var scrollMonitor = require("./scrollMonitor"); // if you're not using require, you can use the scrollMonitor global.
var myElement = document.getElementById("itemToWatch");
var elementWatcher = scrollMonitor.create( myElement );
elementWatcher.enterViewport(function() {
console.log( 'I have entered the viewport' );
});
elementWatcher.exitViewport(function() {
console.log( 'I have left the viewport' );
});
elementWatcher.isInViewport - true if any part of the element is visible, false if not.
elementWatcher.isFullyInViewport - true if the entire element is visible [1].
elementWatcher.isAboveViewport - true if any part of the element is above the viewport.
elementWatcher.isBelowViewport - true if any part of the element is below the viewport.
For a more up-to-date way using getBoundingClientRect():
var isInViewport = function (elem) {
var bounding = elem.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
Returns true if the element in completely in the viewport, and false if it’s not.
var myElem = document.querySelector('#draggable');
if (isInViewport(myElem)) {
// Do something...
}
Complete explanation found here.
My solution is using the given code example, and it will show you an overall idea of how to determine whether the li element is visible. Check out the jsFiddle which contains code from your question.
The jQuery .offset() method allows us to retrieve the current position of an element relative to the document. If you click on an li element inside the draggable, your offset from the top will be between 0 and 500 and the offset from the left should be between 0 and 500. If you call the offset function of an item that is not currently visible, the offset will either be less than 0 or greater than 500 from either the top or left offset.
If its not a daunting task I always like to code what I need from 'scrath' it gives me more flexibility when having to modify or debug, hence why I would recommend looking into using jQuery's offset function instead of using a plugin. If what you are trying to accomplish is fairly simple, using your own function will give you one less library to load.
I m using (checks whether an element is at least partially in the view) following code:
var winSize;
function getWindowSize() {
var winW,WinH = 0;
if (document.body && document.body.offsetWidth) {
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
}
if (document.compatMode == 'CSS1Compat' &&
document.documentElement &&
document.documentElement.offsetWidth) {
winW = document.documentElement.offsetWidth;
winH = document.documentElement.offsetHeight;
}
if (window.innerWidth && window.innerHeight) {
winW = window.innerWidth;
winH = window.innerHeight;
}
return {w:winW, h:winH};
}
winSize = getWindowSize();
function inView(element) {
var box = element.getBoundingClientRect();
if ((box.bottom < 0) || (box.top > winSize.h)){
return false;
}
return true;
}

Categories