滚动向下时,滚动100vh到底部。

7

我希望能够实现与http://www.squaredot.eu/#Intro相同的效果。

如果我向下滚动,页面主体必须向底部滚动100vh。同样,如果向上滚动,页面主体必须向上滚动100vh。我已经尝试了一些方法,但并没有成功。

HTML:

<!DOCTYPE html>
<html>
<head>
    <title> Log In </title>
    <link href="main.css" rel="stylesheet" type="text/css">
</head>
    <body>
        <div id="e1"></div>
        <div id="e2"></div>
        <div id="e3"></div>
        <div id="e4"></div>
        <div id="e5"></div>
    </body>
</html>

CSS:

body, html {
  height: 100%;
  margin: 0;
  padding: 0;
}

#e1 {
    width: 100%;
    height: 100vh;
    background-color: red;
}

#e2 {
    width: 100%;
    height: 100vh;
    background-color: green;
}

#e3 {
    width: 100%;
    height: 100vh;
    background-color: yellow;
}

#e4 {
    width: 100%;
    height: 100vh;
    background-color: blue;
}

#e5 {
    width: 100%;
    height: 100vh;
    background-color: orange;
}

JAVASCRIPT

document.addEventListener('scroll', function(e) {
    var currScroll = document.body.scrollTop;
    document.body.scrollTop = calc(~"currScroll + 100vh");
 }

);

可能是重复的问题:jquery平滑滚动到锚点? - starcorn
我在那里找不到解决方案。我认为'100vh'是问题所在。 - Soccerlife
3个回答

7
一种解决方案是使用 CSS 中的 transform(就像你链接的网站正在做的那样)。
将以下内容添加为 CSS:
body {
    transform: translate3d(0px, 0px, 0px);
    transition: all 700ms ease;
}

并且这是JavaScript

var pageHeight = window.innerHeight;

document.addEventListener('scroll', function(){
  document.body.scrollTop = 0;
});

document.addEventListener('wheel', function(e) {
  //console.log(e.deltaY);
  if(e.deltaY > 0) {
    scrollDown();
  } else {
    scrollUp();
  }
 }
);

function scrollDown() {
  document.body.style.transform = 'translate3d(0px, -'+ pageHeight + 'px, 0px)';
}

function scrollUp() {
  document.body.style.transform = 'translate3d(0px, 0px, 0px)';
}

这只适用于元素1和2,但这是一个开始,您可以学习如何实现其他步骤!

示例链接: https://jsbin.com/titaremevi/edit?css,js,output


更新:

这是完全可行的解决方案:

var pageHeight = window.innerHeight;
var isAnimating = false;
document.body.style.transform = 'translate3d(0px,0px,0px)';

document.addEventListener('scroll', function(e){
  document.body.scrollTop = 0;
});
document.addEventListener('wheel', wheelListener);

function wheelListener(e) {
  if(e.deltaY > 0) {
    scrollPage(-pageHeight);
  } else {
    scrollPage(+pageHeight);
  }
}

function scrollPage(scrollSize) {
  if(isAnimating){
    return;
  }
  isAnimating = true;
  var yPos = getNewYPos(scrollSize);
  document.body.style.transform = 'translate3d(0px,'+ yPos + ',0px)';
}

function getNewYPos(add){
  var oldYPos = document.body.style.transform.split(',')[1];
  oldYPos = parseInt(oldYPos.replace(/px/,''));
  var newYPos = oldYPos + add;
  if(newYPos > 0){
    isAnimating = false;
  }
  return Math.min(0, newYPos) + 'px';
}


document.body.addEventListener('transitionend', function(){
  setTimeout(function(){ isAnimating = false; }, 500);
  document.addEventListener('wheel', wheelListener);
})

您可以在这里看到它的运作效果: https://jsbin.com/foxigobano/1/edit?js,output


是的,我明白,但我不知道怎么做。 - Soccerlife
1
我在答案中添加了完整的实现。 - maxgallo

1
我会取消默认的滚动行为,然后使用鼠标滚轮来模拟它。
主要挑战是将vh转换为px。我已经使用了一个带有设置vh的元素进行转换。最终它变得无用,但准备好以防您想要更改滚动条的大小。
工作版本:

// Cancel default scroll.
document.addEventListener('scoll', function(e) {
  e.preventDefault();
});


// Use wheel event to simulate scroll.
document.addEventListener('wheel', function(e) {
   e.preventDefault();
  // #e1 is 100vh, get height in pixels for conversion rate.
  var pxPerVh = document.querySelector('#e1').offsetHeight / 100;
  
  console.log('s', document.querySelector('#e1').offsetHeight, pxPerVh);
  
  // Current scroll.
  var currScroll = document.body.scrollTop;
  
  // Modify scroll 100 vh
  if (e.wheelDelta < 0) { // scroll up
    var newScroll = currScroll - 100 * pxPerVh;
  } else if (e.wheelDelta > 0) { // scroll down
    var newScroll = currScroll + 100 * pxPerVh;
  } else { // no scroll
    var newScroll = 0;
  }
 
 console.log('p', e.wheelDelta, currScroll, newScroll);
  document.body.scrollTop = newScroll;
});
body, html {
  height: 100%;
  margin: 0;
  padding: 0;
}

#e1 {
    width: 100%;
    height: 100vh;
    background-color: red;
}

#e2 {
    width: 100%;
    height: 100vh;
    background-color: green;
}

#e3 {
    width: 100%;
    height: 100vh;
    background-color: yellow;
}

#e4 {
    width: 100%;
    height: 100vh;
    background-color: blue;
}

#e5 {
    width: 100%;
    height: 100vh;
    background-color: orange;
}
<!DOCTYPE html>
<html>
<head>
    <title> Log In </title>
</head>
    <body>
        <div id="e1"></div>
        <div id="e2"></div>
        <div id="e3"></div>
        <div id="e4"></div>
        <div id="e5"></div>
    </body>
</html>

现在,虽然这是您要求的内容,但我认为这不是您真正想要的。我理解您想要滚动到下一个div。为此,我将重用该逻辑并注册到上次滚动到的#eX,使用document.querySelector('#eX').scrollTop来设置body的滚动。这将解决例如滚动时前一个框中出现1-5像素的问题。
正如您已经在评论中意识到这个问题,我会添加新的解决方案:

// Define range of divs
var currentDiv = 1;
var minDiv;
var maxDiv;
var extraPixel = 0;

var divs = document.querySelectorAll('div[id^="e"]');
for (var i = 0; i < divs.length; i++) {
  var id = parseInt(divs[i].id.slice(1), 10);
  // Check min div
  if (!minDiv) minDiv = id;
  if (minDiv > id) minDiv = id;
  // Check max div
  if (!maxDiv) maxDiv = id;
  if (maxDiv < id) maxDiv = id;
}


// Cancel default scroll.
document.addEventListener('scoll', function(e) {
  e.preventDefault();
});

// Use wheel event to simulate scroll.
document.addEventListener('wheel', function(e) {
   e.preventDefault();

   // Current scroll.
  var currScroll = document.body.scrollTop;
  
  // Decide next element.
  if (e.wheelDelta < 0) { // scroll up
    currentDiv--;
    if (currentDiv < minDiv) currentDiv = minDiv;
  } else if (e.wheelDelta > 0) { // scroll down
    currentDiv++;
    if (currentDiv > maxDiv) currentDiv = maxDiv;
  }

  console.log(currentDiv);

  // Check if there's a next/previous div.
  var goToDiv = document.querySelector('#e' + currentDiv);
  if (goToDiv) {
    var newScroll = goToDiv.offsetTop;
  }
  
  document.body.scrollTop = newScroll;
});
body, html {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  margin: 0;
  padding: 0;
}

#e1 {
    width: 100%;
    height: 100vh;
    background-color: red;
}

#e2 {
    width: 100%;
    height: 100vh;
    background-color: green;
}

#e3 {
    width: 100%;
    height: 100vh;
    background-color: yellow;
}

#e4 {
    width: 100%;
    height: 100vh;
    background-color: blue;
}

#e5 {
    width: 100%;
    height: 100vh;
    background-color: orange;
}
<!DOCTYPE html>
<html>
<head>
    <title> Log In </title>
</head>
    <body>
        <div id="e1"></div>
        <div id="e2"></div>
        <div id="e3"></div>
        <div id="e4"></div>
        <div id="e5"></div>
    </body>
</html>


正如您在“运行代码片段”中所看到的那样,它无法正常工作。页面停留在红色div上,但实际上应该跳转到绿色div上。 - Soccerlife
请看我的上一条评论。 - nitobuendia
我不太明白你的意思,因为我是新手。感谢你的帮助。 - Soccerlife
修复了上一个版本的问题。新增了新版本,可以滚动到下一个 div。 - nitobuendia

0

// Define range of divs
var currentDiv = 1;
var minDiv;
var maxDiv;
var extraPixel = 0;

var divs = document.querySelectorAll('div[id^="e"]');
for (var i = 0; i < divs.length; i++) {
  var id = parseInt(divs[i].id.slice(1), 10);
  // Check min div
  if (!minDiv) minDiv = id;
  if (minDiv > id) minDiv = id;
  // Check max div
  if (!maxDiv) maxDiv = id;
  if (maxDiv < id) maxDiv = id;
}


// Cancel default scroll.
document.addEventListener('scoll', function(e) {
  e.preventDefault();
});

// Use wheel event to simulate scroll.
document.addEventListener('wheel', function(e) {
   e.preventDefault();

   // Current scroll.
  var currScroll = document.body.scrollTop;
  
  // Decide next element.
  if (e.wheelDelta < 0) { // scroll up
    currentDiv--;
    if (currentDiv < minDiv) currentDiv = minDiv;
  } else if (e.wheelDelta > 0) { // scroll down
    currentDiv++;
    if (currentDiv > maxDiv) currentDiv = maxDiv;
  }

  console.log(currentDiv);

  // Check if there's a next/previous div.
  var goToDiv = document.querySelector('#e' + currentDiv);
  if (goToDiv) {
    var newScroll = goToDiv.offsetTop;
  }
  
  document.body.scrollTop = newScroll;
});
body, html {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  margin: 0;
  padding: 0;
}

#e1 {
    width: 100%;
    height: 100vh;
    background-color: red;
}

#e2 {
    width: 100%;
    height: 100vh;
    background-color: green;
}

#e3 {
    width: 100%;
    height: 100vh;
    background-color: yellow;
}

#e4 {
    width: 100%;
    height: 100vh;
    background-color: blue;
}

#e5 {
    width: 100%;
    height: 100vh;
    background-color: orange;
}
<!DOCTYPE html>
<html>
<head>
    <title> Log In </title>
</head>
    <body>
        <div id="e1"></div>
        <div id="e2"></div>
        <div id="e3"></div>
        <div id="e4"></div>
        <div id="e5"></div>
    </body>
</html>


你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接