I've read a bunch of threads but still can't come away with a solution that doesn't use a snap scroll plugin (https://github.com/wtm/jquery.snapscroll).
I was trying to follow this
function scrollTo(a){
//Get current scroll position
var current = (document.all ? document.scrollTop : window.pageYOffset);
//Define variables for data collection
var target = undefined;
var targetpos = undefined;
var dif = 0;
//check each selected element to see witch is closest
$(a).each(function(){
//Save the position of the element to avoid repeated property lookup
var t = $(this).position().top;
//check if there is an element to check against
if (target != undefined){
//save the difference between the current element's position and the current scroll position to avoid repeated calculations
var tdif = Math.abs(current - t);
//check if its closer than the selected element
if(tdif < dif){
//set the current element to be selected
target = this;
targetpos = t;
dif = tdif;
}
} else {
//set the current element to be selected
target = this;
targetpos = t;
dif = Math.abs(current - t);
}
});
//check if an element has been selected
if (target != undefined){
//animate scroll to the elements position
$('html,body').animate({scrollTop: targetpos}, 2000);
}
}
I'm trying to get it to scroll into view
<div class="projectWrap">
Fiddle: http://jsfiddle.net/Dar_T/2h2wjp2L/1/
much like how this site http://www.takumitaniguchi.com/tokyoblue/ has it scroll for its containers.
First you have to find the offset() of the element. Then comparing it to the $(window.scrollTop()), then you can do whatever changes you want. Here's some of the codes:
var project1 = $(".projectWrap").offset();
if($(window).scrollTop() >= project1.top){ // compare window scrolltop to element offset()
$("#tlos1").css("color","blue"); // change navigation
$("#tlos2").css("color","black");
$("#tlos3").css("color","black");
}
Here's the DEMO
Try this out:
var topoffset = 30;
function goTo(tagId) {
var destination = $( '#'+tagId ).offset().top - topoffset;
$("html:not(:animated),body:not(:animated)").animate( { scrollTop: destination}, speed);
});
And create urls with hash like this:
Go to section1
Related
I'm working on a site for a client and trying to implement custom parallax functionality. I have used the following code -
var inView = function(element) {
// get window height
var windowHeight = window.innerHeight;
// Get Element Height
var elementHeight = element.clientHeight;
// get number of pixels that the document is scrolled
var scrollY = window.scrollY || window.pageYOffset;
// get current scroll position (distance from the top of the page to the bottom of the current viewport)
var scrollPosition = scrollY + windowHeight;
var elementPosition = element.getBoundingClientRect().top + scrollY;
var elementScrolled = elementPosition + element.clientHeight + windowHeight
// is scroll position greater than element position? (is element in view?)
if (scrollPosition > elementPosition && scrollPosition < elementScrolled) {
return true;
}
return false;
}
// Get all the elements to be parallaxed
const parallaxElements = {
element: document.querySelectorAll('#header-image img'),
ratio: 0.25
}
// The parallax function
const parallax = elements => {
let items = [...elements.element],
itemRatio = elements.ratio
if ('undefined' !== items && items.length > 0 ) {
items.forEach( item => {
if ( inView(item) == true ) {
item.style.transform = 'translate3d(0, ' + (itemRatio * (window.innerHeight - item.getBoundingClientRect().top)) + 'px ,0)'
}
})
}
}
//If element is in viewport, set its position
parallax(parallaxElements)
//Call the function on scroll
window.onscroll = () => {
parallax(parallaxElements)
}
It's working ok except that when the page is loaded initially and the user starts scrolling, the position of element (#header-image img in this case) changes abruptly. I did some digging and noticed that the value of getBoundingClientRect().top is causing the issue.
When the page is loaded, it has some value, and as soon as the user starts scrolling, it abruptly changes to another value.
I am not able to figure out why this is happening. getBoundingClientRect().top is supposed to get the value of element from top of viewport, right?
Any help is greatly appreciated. Thanks!
Pls check the screenshot of inspect element here -
https://i.stack.imgur.com/RYDvK.jpg
So I have animation that triggers when my scroll position is same as position of element that I want to animate. After scroll to some position, I refresh page and get error that element that i want to animate is not defined. This is code that I am using for animation:
angular.element($window).bind("scroll", function() {
var element = $element.find(".pr-bemax-bodyOfBagger");
if (this.pageYOffset >= element.offset().top - 400) {
var myEl = $element.find("#bulldozer-hand");
myEl[0].classList.add('bulldozer-hand');
}
});
P.S. I don't want to use $timeout.
Just defend against the fact offset will return undefined if the set you call it on is empty:
angular.element($window).bind("scroll", function() {
var element = $element.find(".pr-bemax-bodyOfBagger");
var offset = element.offset(); // <===
if (offset && this.pageYOffset >= offset.top - 400) {
// ^^^^^^^^^^ ^^^^^^
var myEl = $element.find("#bulldozer-hand");
myEl[0].classList.add('bulldozer-hand');
}
});
I have written some jquery to calculate the height of 4 elements by css class and get their height, then compare the height to how far the page has been scrolled. If the page has been scrolled to or past each element then a css class is added which animates the element.
The problem that I am having is that the jquery is adding the classes to all of the elements as soon as the page is scrolled to the first element, instead of adding the class to each as it is scrolled to.
What is wrong with my jquery that it is doing this?
Here is the jsfiddle http://jsfiddle.net/94kP6/7/
This is the jquery part of the code
// element animation scroll detection
(function ($, document, undefined) {
var animation1 = $('.animation1').height();
var animation2 = $('.animation2').height();
var animation3 = $('.animation3').height();
var animation4 = $('.animation4').height();
$(window).scroll(function() {
var winTop = $(window).scrollTop();
if(winTop >= (animation1)){
$('.animation1').addClass("animate-from-left");
}
if(winTop >= (animation2)){
$('.animation2').addClass("animate-from-right");
}
if(winTop >= (animation3)){
$('.animation3').addClass("animate-from-left");
}
if(winTop >= (animation4)){
$('.animation4').addClass("animate-from-right");
}
});
})(jQuery, document);
var animation1 = $('.animation1').height();
var animation2 = $('.animation2').height();
var animation3 = $('.animation3').height();
var animation4 = $('.animation4').height();
needs to be
var animation1 = $('.animation1').offset().top;
var animation2 = $('.animation2').offset().top;
var animation3 = $('.animation3').offset().top;
var animation4 = $('.animation4').offset().top;
or some variant for personal preference, like this:
var animation1 = $('.animation1').position().top - $('.animation1').height();
var animation2 = $('.animation2').position().top - $('.animation2').height();
var animation3 = $('.animation3').position().top - $('.animation3').height();
var animation4 = $('.animation4').position().top - $('.animation4').height();
Here's a fiddle to show you need to use .offset().top instead of .height
http://jsfiddle.net/94kP6/10/
When you use height, you are asking the scroll to wait until the height of the object instead of waiting for the top position of the object
Just change your heights to offsets
UPDATE
http://jsfiddle.net/94kP6/14/
This makes it so the animation can be seen more in the middle of the screen. Just subtract a specified height (in this case, the height of the object) from the offset and it will animate at a higher scrollTop.
You can also do the same thing, only backwards by ADDING a specified amount to the var winTop = $(window).scrollTop(); line, line this: var winTop = $(window).scrollTop() + 250;
I want to have a custom scrollbar on my main div which has buttons to go to certain parts of the div, however anchor points don't seem to work when using the flexcroll plugin (I know i'm doing anchor points correctly because when I disable flexcroll on that div they work fine)
Is their any method I could use to set up the anchor points?
EDIT FOUND SOLUTION: On the buttons I want to click to go to the specific place in the document I can put onclick="Wrapper.fleXcroll.setScrollPos(false,0);"
I've used this function in the past. FYI, I don't know anything about flexcroll, so this is not tested with that:
var isInt = function(val) {
return (parseInt(val, 10) == val);
};
var scrollTo = function(node) {
var pNode = node.parentNode;
var offset = node.offsetTop - pNode.offsetTop;
var pHeight = pNode.clientHeight;
var height = node.clientHeight;
var scrollOffset = pNode.scrollTop;
var buffer = 10;
var scroll = null;
if (scrollOffset > offset) {
scroll = offset - buffer;
} else if (pHeight + scrollOffset < offset + height + buffer) {
scroll = offset + height + buffer - pHeight;
}
if (isInt(scroll)) {
pNode.scrollTop = scroll;
}
};
This is the pure JS version. (example)
Here is an example of a jQuery version, which animates the scroll event: jQuery version
I have a div with overflow set to scroll which essentially streams data line by line off a file. I'd like to scroll automatically to the bottom of the div whenever the stream overflows, but without using a "Click here to scroll to bottom" button.
I already know of the scrollTop = scrollHeight solution, but that requires some kind of event trigger on the client's side. I don't want this element to be interactive; it should scroll by itself.
Is there any way to achieve this?
A lot of the scrollHeight implementations didn't work for me, offsetHeight seemed to do the trick.
Pretty sure that scrollHeight tries to move it to the bottom of the height of the static element, not the height of the scrollable area.
var pane = document.getElementById('pane');
pane.scrollTop = pane.offsetHeight;
There's no way to automatically scroll an element to the bottom. Use element.scrollTop = element.scrollHeight.
If you don't know when the element is going to resize, you could add a poller:
(function(){
var element = document.getElementById("myElement");
var lastHeight = element.scrollHeight;
function detectChange(){
var currentHeight = element.scrollHeight;
if(lastHeight != currentHeight){
element.scrollTop = currentHeight;
lastHeight = currentHeight;
}
}
detectChange();
setInterval(detectChange, 200); //Checks each 200ms = 5 times a second
})();
Some old code of mine with a running example that will stay at the bottom when new content is added, if the user scrolls it will not more it to the bottom.
var chatscroll = new Object();
chatscroll.Pane =
function(scrollContainerId)
{
this.bottomThreshold = 25;
this.scrollContainerId = scrollContainerId;
}
chatscroll.Pane.prototype.activeScroll =
function()
{
var scrollDiv = document.getElementById(this.scrollContainerId);
var currentHeight = 0;
if (scrollDiv.scrollHeight > 0)
currentHeight = scrollDiv.scrollHeight;
else
if (objDiv.offsetHeight > 0)
currentHeight = scrollDiv.offsetHeight;
if (currentHeight - scrollDiv.scrollTop - ((scrollDiv.style.pixelHeight) ? scrollDiv.style.pixelHeight : scrollDiv.offsetHeight) < this.bottomThreshold)
scrollDiv.scrollTop = currentHeight;
scrollDiv = null;
}