jQuery 平滑滚动到页面上的特定元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17722497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scroll smoothly to specific element on page
提问by M P
I want to have 4 buttons/links on the beginning of the page, and under them the content.
我想在页面的开头有 4 个按钮/链接,在它们下面是内容。
On the buttons I put this code:
在按钮上我放了这段代码:
<a href="#idElement1">Scroll to element 1</a>
<a href="#idElement2">Scroll to element 2</a>
<a href="#idElement3">Scroll to element 3</a>
<a href="#idElement4">Scroll to element 4</a>
And under links there will be content:
在链接下会有内容:
<h2 id="idElement1">Element1</h2>
content....
<h2 id="idElement2">Element2</h2>
content....
<h2 id="idElement3">Element3</h2>
content....
<h2 id="idElement4">Element4</h2>
content....
It is working now, but cannot make it look more smooth.
它现在正在工作,但不能让它看起来更平滑。
I used this code, but cannot get it to work.
我使用了此代码,但无法使其正常工作。
$('html, body').animate({
scrollTop: $("#elementID").offset().top
}, 2000);
Any suggestions? Thank you.
有什么建议?谢谢你。
Edit: and the fiddle: http://jsfiddle.net/WxJLx/2/
编辑:和小提琴:http: //jsfiddle.net/WxJLx/2/
采纳答案by Geri Borbás
Just made this javascript only solution below.
刚刚在下面制作了这个javascript唯一的解决方案。
Simple usage:
简单用法:
EPPZScrollTo.scrollVerticalToElementById('signup_form', 20);
Engine object (you can fiddle with filter, fps values):
引擎对象(您可以修改过滤器、fps 值):
/**
*
* Created by Borbás Geri on 12/17/13
* Copyright (c) 2013 eppz! development, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
var EPPZScrollTo =
{
/**
* Helpers.
*/
documentVerticalScrollPosition: function()
{
if (self.pageYOffset) return self.pageYOffset; // Firefox, Chrome, Opera, Safari.
if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Internet Explorer 6 (standards mode).
if (document.body.scrollTop) return document.body.scrollTop; // Internet Explorer 6, 7 and 8.
return 0; // None of the above.
},
viewportHeight: function()
{ return (document.compatMode === "CSS1Compat") ? document.documentElement.clientHeight : document.body.clientHeight; },
documentHeight: function()
{ return (document.height !== undefined) ? document.height : document.body.offsetHeight; },
documentMaximumScrollPosition: function()
{ return this.documentHeight() - this.viewportHeight(); },
elementVerticalClientPositionById: function(id)
{
var element = document.getElementById(id);
var rectangle = element.getBoundingClientRect();
return rectangle.top;
},
/**
* Animation tick.
*/
scrollVerticalTickToPosition: function(currentPosition, targetPosition)
{
var filter = 0.2;
var fps = 60;
var difference = parseFloat(targetPosition) - parseFloat(currentPosition);
// Snap, then stop if arrived.
var arrived = (Math.abs(difference) <= 0.5);
if (arrived)
{
// Apply target.
scrollTo(0.0, targetPosition);
return;
}
// Filtered position.
currentPosition = (parseFloat(currentPosition) * (1.0 - filter)) + (parseFloat(targetPosition) * filter);
// Apply target.
scrollTo(0.0, Math.round(currentPosition));
// Schedule next tick.
setTimeout("EPPZScrollTo.scrollVerticalTickToPosition("+currentPosition+", "+targetPosition+")", (1000 / fps));
},
/**
* For public use.
*
* @param id The id of the element to scroll to.
* @param padding Top padding to apply above element.
*/
scrollVerticalToElementById: function(id, padding)
{
var element = document.getElementById(id);
if (element == null)
{
console.warn('Cannot find element with id \''+id+'\'.');
return;
}
var targetPosition = this.documentVerticalScrollPosition() + this.elementVerticalClientPositionById(id) - padding;
var currentPosition = this.documentVerticalScrollPosition();
// Clamp.
var maximumScrollPosition = this.documentMaximumScrollPosition();
if (targetPosition > maximumScrollPosition) targetPosition = maximumScrollPosition;
// Start animation.
this.scrollVerticalTickToPosition(currentPosition, targetPosition);
}
};
回答by Daniel Sawka
Super smoothly with requestAnimationFrame
超级顺利 requestAnimationFrame
For smoothly rendered scrolling animation one could use window.requestAnimationFrame()
which performs better with renderingthan regular setTimeout()
solutions.
为了顺利呈现滚动动画一个可以使用window.requestAnimationFrame()
它更好地执行与渲染比常规setTimeout()
的解决方案。
A basic example looks like this. Function step
is called for browser's every animation frame and allows for better time management of repaints, and thus increasing performance.
一个基本示例如下所示。step
浏览器的每个动画帧都会调用该函数,并允许更好地管理重绘时间,从而提高性能。
function doScrolling(elementY, duration) {
var startingY = window.pageYOffset;
var diff = elementY - startingY;
var start;
// Bootstrap our animation - it will get called right before next frame shall be rendered.
window.requestAnimationFrame(function step(timestamp) {
if (!start) start = timestamp;
// Elapsed milliseconds since start of scrolling.
var time = timestamp - start;
// Get percent of completion in range [0, 1].
var percent = Math.min(time / duration, 1);
window.scrollTo(0, startingY + diff * percent);
// Proceed with animation as long as we wanted it to.
if (time < duration) {
window.requestAnimationFrame(step);
}
})
}
For element's Y position use functions in other answers or the one in my below-mentioned fiddle.
对于元素的 Y 位置,请使用其他答案中的函数或我下面提到的小提琴中的函数。
I set up a bit more sophisticated function with easing support and proper scrolling to bottom-most elements: https://jsfiddle.net/s61x7c4e/
我通过缓动支持和适当滚动到最底部元素设置了一个更复杂的功能:https: //jsfiddle.net/s61x7c4e/
回答by Sanjay Shr
Question was asked 5 years ago and I was dealing with smooth scroll
and felt giving a simple solution is worth it to those who are looking for. All the answers are good but here you go a simple one.
问题是在 5 年前提出的,我正在处理smooth scroll
并觉得为那些正在寻找的人提供一个简单的解决方案是值得的。所有的答案都很好,但这里有一个简单的答案。
function smoothScroll(){
document.querySelector('.your_class or #id here').scrollIntoView({
behavior: 'smooth'
});
}
just call the smoothScroll
function on onClick
event on your source element
.
只需在您的源smoothScroll
上调用onClick
事件函数element
。
DOCS: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
文档:https: //developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Note: Please check compatibility here
注意:请在此处检查兼容性
3rd Party edit
第三方编辑
Support for Element.scrollIntoView()
in 2020 is this:
Element.scrollIntoView()
2020 年的支持是这样的:
Region full + partial = sum full+partial Support
Asia 73.24% + 22.75% = 95.98%
North America 56.15% + 42.09% = 98.25%
India 71.01% + 20.13% = 91.14%
Europe 68.58% + 27.76% = 96.35%
回答by surfmuggle
Smooth scrolling - look ma no jQuery
平滑滚动 - 看起来没有 jQuery
Based on an article on itnewb.comi made a demo plunk to smoothly scrollwithout external libraries.
基于itnewb.com上的一篇文章,我制作了一个演示 plunk,无需外部库即可平滑滚动。
The javascript is quite simple. First a helper function to improve cross browser support to determine the current position.
javascript 非常简单。首先是一个辅助函数,用于改进跨浏览器支持以确定当前位置。
function currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
}
Then a function to determine the position of the destination element - the one where we would like to scroll to.
然后是一个函数来确定目标元素的位置 - 我们想要滚动到的那个位置。
function elmYPosition(eID) {
var elm = document.getElementById(eID);
var y = elm.offsetTop;
var node = elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
y += node.offsetTop;
} return y;
}
And the core function to do the scrolling
以及进行滚动的核心功能
function smoothScroll(eID) {
var startY = currentYPosition();
var stopY = elmYPosition(eID);
var distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
scrollTo(0, stopY); return;
}
var speed = Math.round(distance / 100);
if (speed >= 20) speed = 20;
var step = Math.round(distance / 25);
var leapY = stopY > startY ? startY + step : startY - step;
var timer = 0;
if (stopY > startY) {
for ( var i=startY; i<stopY; i+=step ) {
setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
leapY += step; if (leapY > stopY) leapY = stopY; timer++;
} return;
}
for ( var i=startY; i>stopY; i-=step ) {
setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
}
return false;
}
To call it you just do the following. You create a link which points to another element by using the id as a reference for a destination anchor.
要调用它,您只需执行以下操作。您可以通过使用 id 作为目标锚点的引用来创建指向另一个元素的链接。
<a href="#anchor-2"
onclick="smoothScroll('anchor-2');">smooth scroll to the headline with id anchor-2<a/>
...
... some content
...
<h2 id="anchor-2">Anchor 2</h2>
Copyright
版权
In the footer of itnewb.com the following is written: The techniques, effects and code demonstrated in ITNewb articles may be used for any purpose without attribution (although we recommend it)
(2014-01-12)
在itnewb.com的页脚中写道:The techniques, effects and code demonstrated in ITNewb articles may be used for any purpose without attribution (although we recommend it)
(2014-01-12)
回答by Thomas
I've been using this for a long time:
我已经使用这个很长时间了:
function scrollToItem(item) {
var diff=(item.offsetTop-window.scrollY)/8
if (Math.abs(diff)>1) {
window.scrollTo(0, (window.scrollY+diff))
clearTimeout(window._TO)
window._TO=setTimeout(scrollToItem, 30, item)
} else {
window.scrollTo(0, item.offsetTop)
}
}
usage:
scrollToItem(element)
where element
is document.getElementById('elementid')
for example.
用法:
scrollToItem(element)
其中,element
是document.getElementById('elementid')
例如。
回答by Andrzej Sala
Variation of @tominko answer. A little smoother animation and resolved problem with infinite invoked setTimeout(), when some elements can't allign to top of viewport.
@tominko 答案的变化。当某些元素无法与视口顶部对齐时,动画更流畅并解决了无限调用 setTimeout() 的问题。
function scrollToItem(item) {
var diff=(item.offsetTop-window.scrollY)/20;
if(!window._lastDiff){
window._lastDiff = 0;
}
console.log('test')
if (Math.abs(diff)>2) {
window.scrollTo(0, (window.scrollY+diff))
clearTimeout(window._TO)
if(diff !== window._lastDiff){
window._lastDiff = diff;
window._TO=setTimeout(scrollToItem, 15, item);
}
} else {
console.timeEnd('test');
window.scrollTo(0, item.offsetTop)
}
}
回答by aniltilanthe
You could also check this great Blog - with some very simple ways to achieve this :)
您还可以查看这个很棒的博客 - 使用一些非常简单的方法来实现这一点:)
https://css-tricks.com/snippets/jquery/smooth-scrolling/
https://css-tricks.com/snippets/jquery/smooth-scrolling/
Like (from the blog)
喜欢(来自博客)
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
// Scroll to a certain element
document.querySelector('.hello').scrollIntoView({
behavior: 'smooth'
});
and you can also get the element "top" position like below (or some other way)
并且您还可以获得如下所示的元素“顶部”位置(或其他方式)
var e = document.getElementById(element);
var top = 0;
do {
top += e.offsetTop;
} while (e = e.offsetParent);
return top;
回答by Feedthe
you can use this plugin. Does exactly what you want.
你可以使用这个插件。正是你想要的。
回答by hev1
You can use a for loop with window.scrollTo and setTimeout to scroll smoothly with plain Javascript. To scroll to an element with my scrollToSmoothly
function: scrollToSmoothly(elem.offsetTop)
(assuming elem
is a DOM element).
您可以使用带有 window.scrollTo 和 setTimeout 的 for 循环来使用纯 Javascript 平滑滚动。使用我的scrollToSmoothly
函数滚动到一个元素:(scrollToSmoothly(elem.offsetTop)
假设elem
是一个 DOM 元素)。
function scrollToSmoothly(pos, time){
/*Time is only applicable for scrolling upwards*/
/*Code written by hev1*/
/*pos is the y-position to scroll to (in pixels)*/
if(isNaN(pos)){
throw "Position must be a number";
}
if(pos<0){
throw "Position can not be negative";
}
var currentPos = window.scrollY||window.screenTop;
if(currentPos<pos){
var t = 10;
for(let i = currentPos; i <= pos; i+=10){
t+=10;
setTimeout(function(){
window.scrollTo(0, i);
}, t/2);
}
} else {
time = time || 2;
var i = currentPos;
var x;
x = setInterval(function(){
window.scrollTo(0, i);
i -= 10;
if(i<=pos){
clearInterval(x);
}
}, time);
}
}
If you want to scroll to an element by its id
, you can add this function (along with the above function):
如果你想通过它滚动到一个元素id
,你可以添加这个函数(连同上面的函数):
function scrollSmoothlyToElementById(id){
var elem = document.getElementById(id);
scrollToSmoothly(elem.offsetTop);
}
Demo:
演示:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element<p/>
<button onClick="scrollToSmoothly(Number(0))">Scroll back to top</button>
</div>
<script>
function scrollToSmoothly(pos, time){
/*Time is only applicable for scrolling upwards*/
/*Code written by hev1*/
/*pos is the y-position to scroll to (in pixels)*/
if(isNaN(pos)){
throw "Position must be a number";
}
if(pos<0){
throw "Position can not be negative";
}
var currentPos = window.scrollY||window.screenTop;
if(currentPos<pos){
var t = 10;
for(let i = currentPos; i <= pos; i+=10){
t+=10;
setTimeout(function(){
window.scrollTo(0, i);
}, t/2);
}
} else {
time = time || 2;
var i = currentPos;
var x;
x = setInterval(function(){
window.scrollTo(0, i);
i -= 10;
if(i<=pos){
clearInterval(x);
}
}, time);
}
}
function scrollToDiv(){
var elem = document.querySelector("div");
scrollToSmoothly(elem.offsetTop);
}
</script>
回答by esnezz
Why not use CSS scroll-behaviorproperty
为什么不使用 CSS滚动行为属性
html {
scroll-behavior: smooth;
}
The browser support is also good https://caniuse.com/#feat=css-scroll-behavior