Smooth cross-browser diagonal scrolling with jQuery - javascript

Depending on the vertical scrolling of the page I move a <div> called container horizontally:
scrollElement.scroll(function() {
var offsetLeft = scrollElement.scrollTop() / x;
container.css({ left: offsetLeft + 'px' });
});
This successfully creates a diagonal scrolling effect when the user scrolls vertically.
The scrolling is barely acceptable in Firefox but very jumpy in Google Chrome: Chrome fails to sync the movement on the x- and the y-axis when you scroll too quickly and therefore first scrolls down and then adjusts the x-offset.
Firefox however just lags when you scroll too quickly.
Is there a better way to implement this "diagonal scrolling"?
Is it possible to make it more smooth?
I basically want the div not to scroll too far down without correcting the x-coordinates every time.

You could try it as an animation instead of setting the CSS for the container offset directly.
scrollElement.scroll(function() {
var offsetLeft = scrollElement.scrollTop() / x;
container.stop(true, false); // Stop the current animation, likely
// caused by a previous scroll event fire.
container.animate({ left: offsetLeft + 'px' });
});

Related

Problem with scrolldown in slow manner using javascript

I needed JavaScript for automatic scroll down in a smooth/slow manner.
I have a form with many radio buttons which is quite similar to survey form.
I used script from the below mentioned link. This link works fine smoothly for scrolling downwards.
But problem comes when you reach the bottom of page and cannot scroll upwards.
I am not so good in JavaScript. Does anyone here has solution or fix to this?
Link to Stack Overflow thread:
Slow down onclick window.scrollBy
function scrollByRate(y, rate)
{
//calculate the scroll height
var scrolling = Math.max( document.getElementsByTagName('html')[0].scrollTop, document.body.scrollTop);
//save the old value as "static" var
arguments.callee.tmp = arguments.callee.tmp || scrolling + y;
//make a little scrolling step
window.scrollBy(0, (arguments.callee.tmp - scrolling) / rate);
//are we arrived? if no, keep going recursively, else reset the static var
if(arguments.callee.tmp - scrolling > 100) setTimeout(function() { scrollByRate(y, rate); }, 10);
else arguments.callee.tmp = undefined;
}
Scrolling down slowly
I can see your approach having a negative impact on performance. It looks like the browser will block until the target scroll destination has been reached.
My suggestion is to use what is out there for smooth scrolling already. The scrollTo method of any scrollable pane (e.g. window object but also a scrollable div for example) has a "behavior" property that you can set to "smooth", e.g.:
window.scrollTo({
top: 100,
left: 100,
behavior: 'smooth'
});
Keep in mind that the compatibility at the time of writing is limited to Chrome, Firefox, Edge and Opera which means you'll have problems on Internet Explorer and Safari (so all Apple products). I myself use a polyfill to get the smooth scrolling back on my application, this one in particular: https://github.com/iamdustan/smoothscroll

Smooth scrolling page when using jQuery ui resizable

So what I want to know is how can I scroll the page down smoothly as I resize a div past the bottom of the browser.
So far what I have set up is that when you resize the div and it gets to the last 30px of of the browser, it starts to scroll the page down. That part works, but it's jerky when doing so.
My code:
// $maxHeight is set above this, it just takes all the elements within the div and and get's the total height and set that as maxHeight
$('.notifications-drop-down').resizable({
maxHeight: $maxHeight,
minHeight: 400,
handles: {
's': '.ui-resizable-s'
},
resize: function(event, ui){
if((ui.position.top + ui.size.height) > ($(window).scrollTop() + $(window).height() - 30)){
$(window).scrollTop($(window).scrollTop()+10);
}
}
});
What I tried to fix this:
Adding an animate function to the scrollTop to make it smoother
$('html,body').animate({scrollTop: $(window).scrollTop()+30}, 200);
But that does not work smoothly. I have changed the animation duration and it's still not smooth. Does anyone know what I can do it get this to be smooth?
Something I noticed was that when the page scrolls down it does not recognize that the div is in the bottom 30px so it's not recalculating if it should scroll down more (you need to wiggle your cursor while resizing the div for it to work), I did try and add the same code for scrolling down to the resizable's stop function but that didn't help as well.
Thanks for the time.

Can someone explain why this code works-making div stick to top after scoll?

I love that this code works, but I cannot, for anything, wrap my head around WHY it's working?
Here is the jfidddle
Here is the code:
jQuery(document).ready(function($) {
clone = $('div').clone();
$('div').after(clone);
$('div:last').hide();
offset = $('div:first').offset();
var fromtop = offset.top;
$(document).scroll(function() {
doc = $(this);
dist = $(this).scrollTop();
if (dist >= fromtop) {
$('div:last').show();
$('div:first').css({
'position': 'fixed'
});
} else {
$('div:first').css({
'position': 'static'
});
$('div:last').hide();
}
});
});
I guess I am not understanding how scrolltop and offset are interacting or what they REALLY are, as in their true positions on the page. The code says if ScrollTop (the scrollbar position?) is higher than the value of the div's offsettop , then make the div sticky. But if ScrollTop is the position of the scrollbar, isn't it true that sometimes the scroll bar position could be lower than the div's position BEFORE the div is at the top of the page? What is it about being at the top of the page (offsettop of 0?)--and only at the top of the page, never before-- that makes offsettop a smaller value than scrolltop?
Really confused, and I don't want to just copy the code without understanding what it's really doing.
scroll Top is actually how many pixels 'up' the page has moved (or how many pixels you have moved down the page)
Basically all that happens is the .offset sees how far down the page (from the top of the page) the 'sticky' menu is
When you scroll to that point the bar becomes fixed (which is basically relative to the window instead of the document)
When you scroll back up it just switches back to being positioned in the document.
For clarity
.offset = 200px say - this is how far down the document the sticky menu is
.scrollTop - is 0 when the page loads
When you scroll down the page 201px
.scrollTop > .offSet -> so make the bar fixed (remember fixed is relative to the window - not the document)
If you scroll back up the process is reversed.
It's actually very simple. Let me try if I can make it a bit clear to you:
Whenever you want something (let's say some div) to get fixed on top as you scroll down, you need two things:
You need the current vertical position of your div. And you calculate that by using offset().top
You need to track how much user has scrolled. And you calculate that by using scrollTop()
So in your case, if the current position of your div is top: 100, then as soon as your scrollbar reaches the number 101, your div will get the class of .fixed
By default, the scrollbar vertical position is 0 when the page loads.

How do I move the background image of a DIV based on the scrollbar movement?

I have been looking into parallax effects for vertical scrolling on my web page, and after some research, I'm not sure that what I want to do is technically a parallax effect.
From what I've seen, most parallax effects assume you want to be able to scroll indefinitely with many background images rolling by, or with huge images that repeat.
What I want to do is have the background of two DIVs be filled with a background image as the scroll bar reaches the bottom of the page. Note that I do not want the background images to stretch. I'm assuming to get the effect I want that these images would have a vertical height bigger than most people's viewport, and then their vertical position would change. When the user's scrollbar is at the top, a certain amount of the background is visible, and then it moves vertically to fill the background space as the user scrolls down.
Please see the image below for a visual explanation of the effect I hope to acheive:
The height of the veiwport will vary depending on the length of content inside the inner DIV.
My trouble is that if what I am trying to do is not exactly a parallax effect, then I don't know what else to call it, and my attempts to search by describing it keep landing me back at pages offering tutorials on parallax effects. So I've been stumped by a lack of terminology.
If someone could direct me to how I can control the vertical position of the background depending on the scrollbar position, that would be much appreciated. If this can be done with just CSS that would be great, but I'm assuming some Javascript would be required. A jQuery solution would also work for me.
Update:
After searching using the terms provided in comments, I've got the background image in the outer DIV to almost do what I want with the following code:
$(window).scroll(function () {
var yPos = $("#outerDiv").height() - ($("#outerDIV").height() * ($(window).scrollTop() / $(window).height()));
document.getElementById('outerDIV').style.backgroundPosition="0px " + yPos + "px";
});
It moves the background image in the right direction relative to the scrolling, but what it lacks is constraining that motion to within the viewport. Getting the right proportions based on the viewport and DIV sizes is proving to be just a little beyond my mathematical abilities.
For your requirement, you have to use a jquery parallax plugin to guide this activity, my best suggest it to use a Superscollorama and play with the elements as your wish...
As far as your question, Try this example,
controller.addTween(
'#examples-background',
(new TimelineLite())
.append([
TweenMax.fromTo($('#parallax-it-left'), 1,
{css:{backgroundPosition:"(0 -54px)"}, immediateRender:true},
{css:{backgroundPosition:"(0 -54px)"}}),
TweenMax.fromTo($('#parallax-it-right'), 1,
{css:{backgroundPosition:"(0 -54px)"}, immediateRender:true},
{css:{backgroundPosition:"(0 54px)"}})
]),
1000 // scroll duration of tween
);
You serial vice change as far as your wish...
Try practice this plugin, hope that works for you...
http://johnpolacek.github.io/superscrollorama/
Thanks...
Turns out what I want to acheive is possible with no special plugins, just some carefully thought out math. I did use a little jQuery syntax, but I don't think it's strictly necessary.
The code below has copious notes, so hopefully it's largely explanatory. In summary, you just need to find the position of the background image when the scroll would be at the top, and the position it would be if the scroll bar was at the bottom, and then you can use the percentage of the scrollbar's movement to work out where you are between those two points. It's a little tricker than just that, of course, in that you have to account for the difference between the total height of the scroll bar and where your DIV appears on the page and a few other adjustments, but the details of what I did are below.
What I've done here is just for the "outer DIV" that I described in my question. To get a background to move like the "inner DIV" I described, you'd have to modify the code, presumeably by reversing a few parameters. I haven't done that yet, but it seems like a straightforward task.
Hope others find this code useful. If anyone has suggestions on how it can be made more efficient or better, please let me know.
function moveBG(){
// imageHeight is not the total height of the image,
// it's the vertical amount you want to ensure remains visible no matter what.
var imageHeight = 300;
// Get the maximum amount within the DIV that the BG can move vertically.
var maxYPos = $("#outerDIV").height() - imageHeight;
// Get the amount of vertical distance from the top of the document to
// to the top of the DIV.
var headerHeight = document.getElementById("outerDIV").offsetTop;
// Calculate the BG Y position for when the scrollbar is at the very top.
var bgTopPos = $(window).height() - headerHeight - imageHeight;
// I don't want the image to wander outside of the DIV, so ensure it never
// goes below zero.
if (bgTopPos < 0)
{
bgTopPos = 0;
}
// Calculate the BG Y position when the scrollbar is at the very top.
var bgBottomPos = $(document).height() - $(window).height() - headerHeight;
// To prevent the BG image from getting cut off at the top, make sure
// its position never exceeds the maximum distance from the top of the DIV.
if (bgBottomPos > maxYPos)
{
bgBottomPos = maxYPos;
}
// Subtract the top position from the bottom, and you have the spread
// the BG will travel.
var totalYSpan = bgBottomPos - bgTopPos;
// Get the scrollbar position as a "percentage". Note I simply left it as a
// value between 0 and 1 instead of converting to a "true" percentage between
// 0 and 100, 'cause we don't need that in this situation.
var scrollPercent = ($(window).scrollTop() / ( $(document).height() - $(window).height()));
// The percentage of spread is added to the top position, and voila!
// You have your Y position for the BG image.
var bgYPos = bgTopPos + (Math.round(totalYSpan * scrollPercent));
// Apply it to the DIV.
document.getElementById('outerDIV').style.backgroundPosition="0px " + bgYPos + "px";
}
// Place the BG image correctly when opening the page.
$(document).ready(function() {
moveBG();
});
// Make it update when the scrollbar moves.
$(window).scroll(function () {
moveBG();
});

jquery scrolltop and scrollleft work perfectly, but on iphone they all scroll the other bar to it's home position?

I am using the following jquery code to scroll to a certain position on the page vertically. This works absolutely fine on all browsers and does not affect the horizontal scroll position, however when i try it on an iphone (on mobile safari) in addition to scrolling to the correct place vertically it also scrolls horizontally all the way to the left. Similarly if i use scrollleft it will go to the correct place horizontally but will return to the top of the page. It works fine on everything else and i cannot find any reference to this problem anywhere, i would be immensely grateful if anyone who's come across this could help me out as i'm stumped! I can't even do one after the other (scrollleft then scrollright) as whichever one i do last will cancel out the scroll positon set by the previous one.
if($.browser.opera)
{
$('html').animate(
{
scrollTop: yscroll - 10
},
1000);
}
else
{
$('html, body').animate(
{
scrollTop: yscroll - 10
},
1000);
}
Thanks so much for your help!
Dave
maybe you could first get the current scrollLeft (or scrollTop if you animate scrollLeft) value and then animate both scrollLeft and scrollTop when the user agents tell you it's an iphone
var isiPhone = navigator.userAgent.toLowerCase().indexOf("iphone");
var isiPad = navigator.userAgent.toLowerCase().indexOf("ipad");
var isiPod = navigator.userAgent.toLowerCase().indexOf("ipod");
it's not the best since you will have a different animation, but at least you will end on the same position
there's some issue with iphone/pad iPad / jQuery.animate(scroll) issues

Categories