JQueryを使用せずに要素にスムーズにスクロールしたい-純粋なjavascriptです。ドキュメント内の特定の位置までスムーズにスクロールダウンとスクロールアップの両方が可能な汎用関数が欲しい。
私はjQueryで次のものを使用できることを知っています:
$('html, body').animate({
scrollTop: $('#myelementid').offset().top
}, 500);
Javascriptだけでそれをどのように行うのですか?
これは私がやろうとしていることです:
function scrollToHalf(){
//what do I do?
}
function scrollToSection(){
//What should I do here?
}
<input type="button" onClick="scrollToHalf()" value="Scroll To 50% of Page">
<br>
<input type="button" onClick="scrollToSection()" value="Scroll To Section1">
<section style="margin-top: 1000px;" id="section1">
This is a section
</section>
Jqueryでは、次のようにします。
html, body{
height: 3000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" onClick="scrollToHalf()" value="Scroll To 50% of Page">
<br>
<input type="button" onClick="scrollToSection()" value="Scroll To Section1">
<section style="margin-top: 1000px;" id="section1">
This is a section
</section>
<script>
function scrollToHalf(){
var height = $('body').height();
$('html, body').animate({
scrollTop: height/2
}, 500);
}
function scrollToSection(){
$('html, body').animate({
scrollTop: $('#section1').offset().top
}, 500);
}
</script>
編集:ページ上の特定の位置にスムーズにスクロールできるようにもしたい
編集:CSSソリューションも歓迎です(ただし、JavaScriptソリューションを好むでしょう)
window.scrollTo
およびfor
でsetTimeout
ループを使用すると、プレーンなJavaScriptでスムーズにスクロールできます。特定の要素までスクロールするには、最初の引数として要素のoffsetTopを指定してscrollToSmoothly
関数を呼び出します。
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);
}
}
デモ:
<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>
<p/>
<button onClick="scrollToSmoothly(document.body.offsetHeight)">
Scroll To Bottom
</button>
</div>
<button onClick="scrollToSmoothly(Number(500))">
Scroll to y-position 500px
</button>
<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){
if(time){
var x;
var i = currentPos;
x = setInterval(function(){
window.scrollTo(0, i);
i += 10;
if(i>=pos){
clearInterval(x);
}
}, time);
} else {
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>
正確な時間で特定の位置にスクロールするには、window.requestAnimationFrame
を使用できます。 JSFiddle WebPage Demo: http://jsfiddle.net/4xwnzgj5/embedded/result
function scrollToSmoothly(pos, time){
/*Time is exact amount of time the scrolling will take (in milliseconds)*/
/*Pos is the y-position to scroll to (in pixels)*/
/*Code written by hev1*/
if(typeof pos!== "number"){
pos = parseFloat(pos);
}
if(isNaN(pos)){
console.warn("Position must be a number or a numeric String.");
throw "Position must be a number";
}
if(pos<0||time<0){
return;
}
var currentPos = window.scrollY || window.screenTop;
var start = null;
time = time || 500;
window.requestAnimationFrame(function step(currentTime){
start = !start? currentTime: start;
if(currentPos<pos){
var progress = currentTime - start;
window.scrollTo(0, ((pos-currentPos)*progress/time)+currentPos);
if(progress < time){
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
} else {
var progress = currentTime - start;
window.scrollTo(0, currentPos-((currentPos-pos)*progress/time));
if(progress < time){
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
}
});
}
デモ:
<button onClick="scrollToSmoothly(Number(document.querySelector('div').offsetTop), Number(300))">
Scroll To Div (300ms)
</button>
<button onClick="scrollToSmoothly(Number(document.querySelector('div').offsetTop), Number(200))">
Scroll To Div (200ms)
</button>
<button onClick="scrollToSmoothly(Number(document.querySelector('div').offsetTop), Number(100))">
Scroll To Div (100ms)
</button>
<button onClick="scrollToSmoothly(Number(document.querySelector('div').offsetTop), 50)">
Scroll To Div (50ms)
</button>
<button onClick="scrollToSmoothly(Number(document.querySelector('div').offsetTop), Number(1000))">
Scroll To Div (1000ms)
</button>
<div style="margin: 500px 0px;">
DIV<p/>
<button onClick="scrollToSmoothly(0, 500)">
Back To Top
</button>
<button onClick="scrollToSmoothly(document.body.scrollHeight)">
Scroll To Bottom
</button>
</div>
<div style="margin: 500px 0px;">
</div>
<button style="margin-top: 100px;" onClick="scrollToSmoothly(500, 3000)">
Scroll To y-position 500px (3000ms)
</button>
<script>
function scrollToSmoothly(pos, time){
/*Time is exact amount of time the scrolling will take (in milliseconds)*/
/*Pos is the y-position to scroll to (in pixels)*/
/*Code written by hev1*/
if(typeof pos!== "number"){
pos = parseFloat(pos);
}
if(isNaN(pos)){
console.warn("Position must be a number or a numeric String.");
throw "Position must be a number";
}
if(pos<0||time<0){
return;
}
var currentPos = window.scrollY || window.screenTop;
var start = null;
time = time || 500;
window.requestAnimationFrame(function step(currentTime){
start = !start? currentTime: start;
if(currentPos<pos){
var progress = currentTime - start;
window.scrollTo(0, ((pos-currentPos)*progress/time)+currentPos);
if(progress < time){
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
} else {
var progress = currentTime - start;
window.scrollTo(0, currentPos-((currentPos-pos)*progress/time));
if(progress < time){
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
}
});
}
</script>
または、特定のxおよびy位置にスクロールするwindow.scroll
と、現在の位置からスクロールするwindow.scrollBy
を使用できます。
// 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'
});
デモ:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scroll({
top: elem.offsetTop,
left: 0,
behavior: 'smooth'
});
}
</script>
文書内の特定の位置ではなく、要素までスクロールする必要がある場合は、behavior
をsmooth
に設定してElement.scrollIntoView
を使用できます。
document.getElementById("elemID").scrollIntoView({
behavior: 'smooth'
});
デモ:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div id="myDiv" style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
document.getElementById("myDiv").scrollIntoView({
behavior: 'smooth'
});
}
</script>
最新のブラウザはscroll-behavior
CSSプロパティをサポートします。これは、ドキュメント内のスクロールをスムーズにするために使用できます(Javascriptを必要とせず、アンカータグにhref
#
プラススクロールする要素のid
)。 div
などの特定の要素にscroll-behavior
プロパティを設定して、コンテンツをスムーズにスクロールさせることもできます。
デモ:
html, body{
scroll-behavior: smooth;
}
a, a:visited{
color: initial;
}
<a href="#elem">Scroll To Element</a>
<div id="elem" style="margin: 500px 0px;">Div</div>
CSS scroll-behavior
プロパティは、window.scrollTo
を使用するときにJavascriptでも機能します。
デモ:
html, body{
scroll-behavior: smooth;
}
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scrollTo(0, elem.offsetTop);
}
</script>
scroll-behavior
プロパティがサポートされているかどうかを確認するには、HTML要素のスタイルのキーとして存在するかどうかを確認できます。
var scrollBehaviorSupported = 'scroll-behavior' in document.documentElement.style;
console.log('scroll-behavior supported:',scrollBehaviorSupported);
Element.scrollIntoView()
の使用を検討してください。
私のコメントで述べたように、 scrollIntoView
は考慮すべき適切なオプションです。これは、ブラウザのサポートをさらに強化します。 scrollToSection
関数を実行しようとしています。
ページの中央にスクロールするには、scrollTop
および/またはbody
要素のhtml
プロパティをscrollHeight
の差の半分に設定できます。本体とウィンドウのinnerHeight
上記の計算を requestAnimationFrame
と組み合わせると、設定されます。
上記の提案をコードに組み込む方法は次のとおりです。
function scrollToHalf(duration) {
var
heightDiff = document.body.scrollHeight - window.innerHeight,
endValue = heightDiff / 2,
start = null;
/* Set a default for the duration, in case it's not given. */
duration = duration || 300;
/* Start the animation. */
window.requestAnimationFrame(function step (now) {
/* Normalise the start date and calculate the current progress. */
start = !start ? now : start;
var progress = now - start;
/* Increment by a calculate step the value of the scroll top. */
document.documentElement.scrollTop = endValue * progress / duration;
document.body.scrollTop = endValue * progress / duration;
/* Check whether the current progress is less than the given duration. */
if (progress < duration) {
/* Execute the function recursively. */
window.requestAnimationFrame(step);
}
else {
/* Set the scroll top to the end value. */
document.documentElement.scrollTop = endValue;
document.body.scrollTop = endValue;
}
});
}
function scrollToSection(element) {
/* Scroll until the button's next sibling comes into view. */
element.nextElementSibling.scrollIntoView({block: "start", behavior: "smooth"});
}
#section1 {
margin: 1000px 0;
border: 1px solid red
}
<input type="button" onClick="scrollToHalf()" value="Scroll To 50% of Page">
<br>
<input type="button" onClick="scrollToSection(this)" value="Scroll To Section1">
<section id="section1">
This is a section
</section>