I know this has probably been asked before but I couldn't find the right answer.
I'm trying to have a link, when you click it, scrolls the page to an element with an ID, with just javascript, and I get to control the speed.
I know about:
document.getElementById('youridhere').scrollIntoView();
and that didn't work. It just snapped into view. I also tried scrollBy but that didn't work since it works in increments. I can write it up to check the remaining distance to the element and if it's less than the increment, then only move what's left, but that seems way too bulky.
I tried scrollTo as well but that wasn't helping much either.
Is there a cleaner way of doing this?
This needs to be javascript only. Here is a jquery equivalent:
var top = target.offset().top;
$('html,body').animate({scrollTop: top}, 1000);
There is no built-in way to smooth scroll. I would use setInterval and scrollBy an increment on each iteration, then clearInterval when done.
You could also check the jQuery source to see how they do it.
Related
I'm looking to do something like this. I'm using code from this answer here but the answer is never made entirely clear. They are suggested to use this jquery plugin here but I haven't been able to get it to work. I would go with the first example's code, only, I'm using Foundation 4 and the progress bars are something that come with it and are simpler to create. Also, the animation code provided in the second example is a lot cleaner-- overall, the first example is kinda messy, code heavy, and redundant.
My code is live here. I'm working with the skill bars in the about section. Before the user gets to this point, the animation should be paused. Once the user scrolls to this part of the page, the animation should play.
EDIT: Also, if you have any suggestions to stop the bars from "breaking" out of their containers when you scale the page (this site is meant to be responsive), I would appreciate that as well.
EDIT2: I've noticed as I've been playing with this that overflow: hidden; on .progress fixes my "breaking" issue.. however, when you resize the window, the sizes stay at what they initialized at. I know realistically users visiting my site likely won't be resizing the window a whole lot, but for employers looking at it, it'll kinda be lame if it doesn't work properly. I'm having this same issue with the grumpy-cat button overlays where it initializes at the first size and doesn't resize the overlay after that. Suggestions to this would be really, really appreciated!
If you know where your skill bar is and you know where your screen is at, you only need javascript. (no plugins or weird stuff)
To get the vertical position of your screen it's simple:
window.pageYOffset
To get the vertical position of your div, you just need
div.offsetTop
In your case, I would give an id to the div that wraps all the skill bars and set a loop (window.requestAnimationFrame https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame ) to check if you're within reach of the div (say, if the difference between the window offset and the div is less than some amount).
If the answer is yes, trigger the animation.
The best way to do the animation is by a css transition. (if you need a good intro to css animations here's a video that i found helpful: http://www.youtube.com/watch?v=VoncDvOfUkk )
You can set css animations from javascript.
The idea is that you would set all your "meter" widths to 0. Then in javascript do something like:
div.style.transition = "width 1s";
div.style.width = someValue;
My recommendation for the value to include in the div is some constant fraction of the "progress" div, as in with % as opposed to em or px. This technique should work. (in case you still have issues, you have a window.requestAnimationFrame loop going on so you can recalculate the values at each timestep... although... beware performance).
The reason you were recommended jQuery is because when you're going to have to update all the divs in order to animate them, just writing $(this).find('.meter') and then addClass('.expand') is so much easier.
Hope this helps
Does scrollIntoView() work in all browsers? If not is there a jQuery alternative?
It is supported yes, but user experience is... bad.
As #9bits pointed out, this has long been supported by all major browsers. Not to worry about that. The main problem is the way that it works. It simply jumps to a particular element that may as well be at the end of the page. By jumping to it, users have no idea whether:
page has been scrolled up
page has been scrolled down
they've been redirected elsewhere
The first two can be determined by scroll position, but who says users kept track of scroll position before jump was done? So it's an nondeterministic action.
The last one may be true especially if the page has moving header that gets scrolled out of view and remaining page design doesn't imply anything on being on the same page (if it also doesn't have any total height vertical element like left menu bar). You'd be surprised how many pages have this problem. just check them out yourself. Go to some page, look at it at top, then press End key and look at it again. It is likely that you'll think it's a different page.
Animated scrollintoview jQuery plugin to the rescue
That's why there still are plugins that perform scroll into view instead of using native DOM function. They usually animate scrolling which eliminates all 3 issues outlined above. Users can easily keep track of the movement.
Looks like it does: http://www.quirksmode.org/dom/w3c_cssom.html
I use Matteo Spinnelli's iScroll-4 and it works in iOS safari as well. It has three methods scrollTo, scrollToElement and scrollToPage. Let's say you have an unordered list of elements wrapped inside a div. As Robert Koritnik has written above, you need to have that slight animation to show that you have scrolled. The below method achieves that effect.
scrollToElement(element, time);
read please about scrollIntoViewIfNeeded
if(el.scrollIntoViewIfNeeded){
el.scrollIntoViewIfNeeded()
}else{
el.scrollIntoView()
}
You can use jQuery alternative and animate <html> and <body> elements:
$('html, body').animate({
scrollTop: $("#myElem").offset().top
}, 1000);
Have not tried this, but seems like piggybacking on built in scrollIntoView function would save much code. Here is what I would do if you want animated action:
Cache current scroll position of the container as START POSITION
run built in scrollIntoView
Cache the scroll position again as the END POSITION
Return container back to START POSITION
Animate scrolling to END POSITION
Css solved it guys!!
I picked the target id with #idSelected and styled it with css "scroll-margin-top" and defined my margin top in rems (use what ever measurement that suits you).
#idSelected {
scroll-margin-top: 10rem;
}
I have the following working code to make a element of my scrollbox visible:
var next = elements.item(i+1);
var xpcomInterface = scroll.boxObject.QueryInterface(
Components.interfaces.nsIScrollBoxObject);
xpcomInterface.ensureElementIsVisible(elements);
But I would like to make a smooth-scroll (slow or not). Any idea how to do it?
update
By the way, it's for Mozilla environment.
The simplest way would be to just use a setTimeout function and just keep moving the top and left value on the element's div by a small number, until you get where you want to be.
You may want to experiment with how fast to make it move, as there is a trade-off with smooth, and the fact that it should reach the endpoint in some reasonable time.
Update:
I forgot, you will want to keep calling the setTimeout until you reach the final destination, otherwise it won't redraw the browser window.
I don't know exactly how to do it, but here's a Chrome Extension called "Smooth Scroll" where you can potentially pick through the code to see what they do and maybe get you in the right direction.
PS I love this extension.
jQuery .animate() with accelerated motion can be kind of smooth (see demo for animate with a relative move). And with a plug-in, there are other easing equations it can use.
I have written a scroller function which will scroll one div inside another one. The idea is to use the setInterval method to change the margin of the inner element to simulate a scrolling div.
The problem I am facing is that the scrolling is not entirely smooth. Sometimes it stops for a split-second and then it resumes. What can I do to remove these random hiccups? (I am moving 1px per 20 milliseconds)
three comments that might make an answer:
i see you are already using jQuery. it has scroll functions that have been smooth for me.
have you tried fractional positions? as in scrollerMarginTop -= 0.7;
also, you should probably clearInterval() unless the user can move the div and you want it to resume scrolling back into place.
if it works great until you interact with it, consider clearing the interval and waiting until interaction occurs and re-intervaling.
hth
It was quite some time ago that you asked this question, but if you haven't found a working solution you could try Smooth Div Scroll which is a jQuery plugin that does exactly what you describe: scroll one div inside another one.
What I want to do is scroll down the window when I expand elements in my page.
The effect I am trying to achieve is like the Stack Overflow comments. If it expands beyond the page, it scrolls down to fit all the comments in the window.
What is the best way of doing this?
Edit: I am using JQuery.
This jQuery plugin worked well for me:
http://demos.flesler.com/jquery/scrollTo/
If you have the advantage of using Prototype, you can use $(element).scrollTo().
Otherwise, the general idea is to calculate the cumulative offset of the element, then set window.scrollTop (and window.scrollLeft) accordingly.
You can do it nicely with Scriptaculous (built on top of Prototype):
new Effect.ScrollTo('someDiv',{...some parameters...})
It gives you finer control than Prototype alone (delay before start, duration and callback events (such as afterFinish) that allow you to trigger other effects or whatever you choose. You can make it scroll smoothly and nicely, so the page doesn't suddenly jump.
If you know what the next element in the source is you could actually just jump to that element (location.href="#..."). This would use the browser's native 'scrolling' and not use any libraries.
You could use this code wich is okay but not perfect.
Based on the suggestion by blonkm
function scrollTo( Selector ){
$(Selector).before("<a name='scroll' id='scroll'></a>");
document.location.hash = 'scroll';
$('scroll').remove();
}
This should work.
Requires jQuery but you already say your using that.