Change margin-top as user scrolls - javascript

I am trying to get a div to scroll up at the same amount of pixels as the user scrolls down the page. For example, in Google Chrome when using the mouse wheel, it scrolls down in about 20px intervals. But when you scroll down using the handle, the scrolling amount varies.
Here is my code so far:
var scrollCtr = 50;
$(window).scroll(function(){
scrollCtr = scrollCtr - 20;
$('div.nexus-files').css('margin-top', scrollCtr + 'px');
});
There are a few problems with this:
The user scrolling varies
It needs to subtract from margin-top if scrolling down and add to margin-top if scrolling up
Here is an example:
http://www.enflick.com/
Thanks for the help

You're doing it the wrong way, what you are trying to do should be done using position: fixed on div.nexus-files
div.nexus-files{position: fixed; top: 0;}
but anyway - if you still want to know what you can do with the scroll event - you better get to scrollTop of the document and set the margin-top to the same value
window.onscroll = function(event){
var doc = document.documentElement, body = document.body;
var top = (doc && doc.scrollTop || body && body.scrollTop || 0);
document.getElementById('nexus-files_id').style.marginTop = top+'px';
}
I'm using pure Javascript instead of jQuery because of the overhead that might be crucial when the browser need to calculate stuff in a very short amount of time (during the scrolling). [this can be done even more efficient by storing reference to the element and the doc... but you know..)
I used id based selector to get the specific element instead of class based
AND I SAY AGAIN - this is not how you should do what you were trying to do

Why not using the actual scroll offset as reference or position ?
// or whatever offset you need
var scrollOffset = document.body.scrollTop + 20;
// jQuery
var scrollOffset = $("body").scrollTop() + 20;

Finally Got it
Here is the code I used to accomplish the task.
Most of the code is from http://enflick.com and I modified it to work with my individual situation.
jQuery(window).load(function(){
initParallax();
});
// parallax init
function initParallax(){
var win = jQuery(window);
var wrapper = jQuery('#wrapper');
var bg1 = wrapper.find('.nexus-files');
var koeff = 0.55;
if (bg1.length) {
function refreshPosition(){
var scrolled = win.scrollTop();
var maxOffsetY1 = 450;
var offsetY1 = scrolled * koeff;
var offsetY2 = scrolled * koeff - (maxOffsetY1 * koeff - offsetY1);
if (offsetY1 <= maxOffsetY1 * koeff - offsetY1) {
bg1.css("margin-top", +-offsetY1+"px");
//alert(+-offsetY1+"px");
}
}
refreshPosition();
win.bind('resize scroll', refreshPosition);
}
}

Related

How do I animate opacity change inside a waypoint function based on scroll position?

I am working on a project, here: https://github.com/erinreiss/spaceship1/tree/ministory1
And I am looking to make a div#landing to go from opacity:1 to opacity:0 within 200 pixels of scrolling, based on scroll position. I was able to do it successfully like this:
var target = $('#landing');
var targetHeight = 200;
$(document).scroll(function(e){
var scrollPercent = (targetHeight - window.scrollY) / targetHeight;
if(scrollPercent >= 0){
target.css('opacity', scrollPercent);
}
});
Now, I want to use waypoints to trigger this same effect but at a different time. I want instead of it firing as the div#landing moves out of the viewport, it instead fires as a defined Waypoint (in this case, a different div#intro1) is scrolled past.
This is my attempt:
var target = $('#landing');
var targetHeight = 200;
var intro1 = $('#intro1').waypoint(function (direction) {
console.log('bam!');
$(document).scroll(function(e){
var scrollPercent = (targetHeight - window.scrollY) / targetHeight;
if(scrollPercent >= 0){
target.css('opacity', scrollPercent);
}
})
}, {offset: 200});
The waypoint fires, but (alas) the scrolling opacity changer does not work...
Any advice? Thank you!!
ps - The other thread with this question is answered with code no longer available :(
How do I animate on scroll inside a waypoint function?
I didn't solve this problem, but I did hack something together close to what I wanted... It allows me to use the scroll position of an overflow element to trigger and define the level of opacity on another element.
See solution here:
https://github.com/erinreiss/spaceship1/tree/ministory1
var target = $('#intro1inner');
$('#intro1inner').scroll(function(){
//define a variable that will be how much the target has scrolled from its original position
var changeA = target.scrollTop()
console.log('changeA:' + changeA)
// I want my change in opacity (from 0-1 to take place over 250px)
var scrollPercent = changeA / 250;
console.log('scrollPercent:' + scrollPercent)
});

Position fixed, but scroll on <body>

I have this situation:
my website, which I am creating, has a left sidebar, which must be set to height 100%, while scrolling the webpage, and the content inside it is definitely over 1000px height.
because of the height of the content, I get vertical scroll on this sidebar element, and when my content has enough content, I get another scroll for this section.
What I have to do is to, somehow, transfer, scroll from the "fixed" element to the main page scroll...
I hope that you can understand me...
I hope that this screenshot, can also help you to understand what I ask:
link
Thank you in advance for you answers.
Your question got me interested, so I gave it a try.
You could have your sidebar set up like so:
#sidebar{
position:fixed;
min-height:100%;
top:0;
left:0;
/* ... */
}
Now, to make it scroll, we can play with its margin-top css property:
If we scroll down, we decrement it unless we scrolled past its
height.
If we scroll up, we increment it unless it's above zero.
I created a ScrollingSidebar class with 2 functions in order to deal with that:
// ScrollingSidebar class
// Define some variables and bind events
function ScrollingSidebar(el){
this.sidebar = el;
var that = this;
that.updateVariables();
document.addEventListener('scroll',function(){that.scrollSidebar();});
window.addEventListener('resize',function(){that.updateVariables();});
}
// Updates variables used for calculation
ScrollingSidebar.prototype.updateVariables = function(){
this.height = parseInt( getComputedStyle(this.sidebar).height );
document.body.style.minHeight = this.height + 'px';
this.winHeight = parseInt( window.innerHeight );
this.previousScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
this.scrollSidebar();
};
// Updates the sidebar's margin-top
ScrollingSidebar.prototype.scrollSidebar = function(){
var curScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
if(this.previousScrollPos < curScrollPos){
this.sidebar.style.marginTop = - Math.min(-parseInt( getComputedStyle(this.sidebar).marginTop ) + (curScrollPos - this.previousScrollPos),
this.height-this.winHeight) + 'px';
} else {
this.sidebar.style.marginTop = Math.min(0,parseInt( getComputedStyle(this.sidebar).marginTop ) + this.previousScrollPos-curScrollPos) + 'px';
}
this.previousScrollPos = curScrollPos;
};
You can use it like so:
// Create an instance of ScrollingSidebar
var sidebar = document.getElementById('sidebar');
var x = new ScrollingSidebar(sidebar);
JS Fiddle Demo (with a small amount of content)
JS Fiddle Demo (with a lot of content)
Note: I did not take the time to comment my code very well, but if you have any question about it or any problem with it, feel free to ask.
If your website is responsive and you don't want this method to be used on small screens, you might want to consider using a condition to disable it.

Javascript DIV Movement on scroll

NIm creating an animation that moves a div incrementally on scroll. I'm close but I don't think my code is the most efficient and I don't know how to adapt it to add more arguments. So for instance, hitting a certain height on the page will then move the object right and stop moving it down. Below is my JS and the codepen can be found at;
http://codepen.io/anon/pen/KxHwu - Original
http://codepen.io/anon/pen/DLxqg - Messing about with moving right
var lastScrollTop = 0;
var boxPosition = $('#box').position();
var row2Position = $('#row2').position();
var distance = $('#row2').offset().top,
$window = $(window);
console.log(distance);
$window.scroll(function() {
if ( $window.scrollTop() >= distance - 400 ) {
var st = $(window).scrollTop();
console.log(st);
$('#box').css({top: 0 + st});
//CODE NOT WORKING
if(st >= 270) {
var boxPos = $('#box').position();
console.log(boxPos.left);
$('#box').css({left: boxPos.left + st});
}
//
lastScrollTop = st;
}
});
I'm looking for the box to start scrolling like it does, then when it hits half of row 2 scroll right.
I hope I have explained this in an easy way!
Thanks
http://codepen.io/anon/pen/tHwlq
Here is an example of how to do it; you'll need to tweak the numbers to make it work as you plan.
var $window = $(window);
var $box = $("#box");
$window.scroll(function() {
var scrollTop = $window.scrollTop();
if (scrollTop >= 250 && scrollTop < 400) {
$box.css({top: -250 + scrollTop});
} else if(scrollTop >= 400 && scrollTop < 600) {
$box.css({left: (50+(scrollTop-400)/2)+"%"})
}
});
If your project has numerous elements like this, I'd recommend the ScrollMagic (http://janpaepke.github.io/ScrollMagic/) library.
As far as efficiency is concerned I'd recommend the following:
1) Cache the jQuery selectors (note $box variable). Otherwise, jQuery will have to query the DOM on every scroll event.
2) Cache scrollTop rather then querying it multiple times within the event callback.
3) Although left and top work, using the transform: translate() property is more efficient, especially on mobile devices. (https://developer.mozilla.org/en-US/docs/Web/CSS/transform). However, on most mobile devices, scroll events only fire at the completion of a scroll, not while a page is scrolling.

synchronising two divs scroll is not smooth in iOS

--> Please goto Edit part of this Question
I want to synchronise scroll bar of two divs and this is how I am doing it
var div1 = document.getElementById('element1'),
div2 = document.getElementById('element2');
div1.addEventListener('touchmove', scrolled, false);
div2.addEventListener('touchmove', scrolled, false);
function getscrollTop(node) {
return node.pageYOffset || node.scrollTop;
}
function scrolled() {
var node = this, scrollTop = getscrollTop(node);
var percentage = scrollTop / (node.scrollHeight - node.clientHeight);
var other = document.getElementById({
"element1": "element2",
"element2": "element1"
}[node.id]);
other.scrollTop = percentage * (other.scrollHeight - other.clientHeight);
};
Fiddle -> used scroll instead touchmove
But the problem is it is flickering in low end devices and would like to make it smooth in event low end devices.
Edit
I have used below code to smoothen the scrolling
var children = document.querySelectorAll('.scrolldiv');
var getscrollTop = function(node) {
return node.pageYOffset || node.scrollTop;
}, toInt = function(n) {
return Math.round(Number(n));
};
window.setInterval(function() {
var scrollTop = getscrollTop(children[0]);
var percentage = scrollTop / (children[0].scrollHeight - children[0].clientHeight);
var oscrollTop = percentage * (children[1].scrollHeight - children[1].clientHeight);
// console.log(1);
children[1].scrollTop = toInt(oscrollTop);
}, 2);
It is smoother in Desktop browsers but in iOS browser, when setting second DIv's scroll it is jerking, jerking in the sense setting scrollTop once scrolling is completed, not while scrolling.
If you round your scroll value numbers to integers then this problem goes away :
http://jsfiddle.net/2Cj4S/15/
I just used a rounding function :
function toInt(n){ return Math.round(Number(n)); };
and this seems to have fixed it. Double values really confused GUI widgets like scrollbars, and 2D drawing.
I don't see why you have to calculate a new percentage here, value which you hand over to the second scroll.. that's probably the reason for the jerking.. instead you could simply take the scroll value from the first scroll and assign it directly to the other scroll.. This will remove the jerky-ness in the other scroll.. and synchronising them..
I just added the following line to the bottom of your scrolled function..
other.scrollTop = getscrollTop(node);
The modified function:-
function scrolled() {
var node = this,
scrollTop = getscrollTop(node);
var id = node.id;
var percentage = getscrollTop(node) / (node.scrollHeight - node.clientHeight);
var other = document.getElementById({
"element1": "element2",
"element2": "element1"
}[id]);
var oscrollTop = percentage * (other.scrollHeight - other.clientHeight)
//other.scrollTop = oscrollTop;
//Please note that I have commented out the above line.. and added the following line
other.scrollTop = getscrollTop(node);
};
I hope this the behaviour you were hoping for, i tested it out on jsfiddle, both scrolls are well synchronised.

Javascript dialog is programmed to move when the page scrolls, but it flickers. Can this be fixed?

I've written some jQuery code to display a box with data in the corner of the users' web browser. I'm using the .scroll event to make the box stay in the corner as the user scrolls up and down the page. Let me emphasize that I am not using jquery-ui dialog.
The only problem is that the box flickers as the page scrolls. I'm afraid that there will be no cross-browser solution to this problem as the different browsers seem to behave differently with scrolling. Barring a cross-browser solution, an IE solution would be nice (My web application is designed to be used by a specific group of about 100 users in my organization.)
Here are snippets of the relative code:
ExternalScroll: function () {
LittleBlackBook.setPosition();
}
setPosition: function () {
var scrollPosition = $(self).scrollTop();
var cssTop = LittleBlackBookStatic.determineCssTop(this.height, this.isTop, this.vOffset, scrollPosition);
var cssHeight = LittleBlackBookStatic.determineCssHeight(this.height);
var cssLeft = LittleBlackBookStatic.determineCssLeft(this.width, this.isLeft, this.hOffset);
var cssWidth = LittleBlackBookStatic.determineCssWidth(this.width);
this.jQueryObj.css('top', cssTop);
this.jQueryObj.css('height', cssHeight);
this.jQueryObj.css('left', cssLeft);
this.jQueryObj.css('width', cssWidth);
}
var LittleBlackBookStatic = {
determineCssTop: function (height, isTop, vOffset, vScroll) {
var windowHeight = $(self).height();
var scrollPosition = $(self).scrollTop();
var newModalTop = isTop ? vOffset + vScroll : windowHeight - height + vScroll - vOffset;
return newModalTop + 'px';
},
determineCssHeight: function (height) {
return height + 'px';
},
determineCssLeft: function (width, isLeft, hOffset) {
var windowWidth = $(self).width();
var newModalLeft = isLeft ? hOffset : windowWidth - width - hOffset;
return newModalLeft + 'px';
},
determineCssWidth: function (width) {
return width + 'px';
}
} // end LittleBlackBookStatic
I'm using jQuery to look up the scroll position as the page scrolls and change the CSS.
Is there a better way; a way that will make it scroll without flickering? If no, then why not?
You should use fixed positioning for that box instead instead of animating it to keep it in the corner.
You'll use less javascript and avoid flickering that comes with animation.

Categories