自定义滚动UX

时间:2016-12-07 23:11:51

标签: javascript jquery html5 css3 scroll

我目前正在开展一个项目,其中所需的用户体验涉及与滚动事件的非常自定义的交互。

要解决的问题: 该页面有X个部分,每个部分的高度等于视口高度height: 100vh;。当用户在视口上向下滚动时,当前可见部分保持原样并且滚动指示器基于滚动的距离阈值(例如,30px)动画化。一旦用户滚动了阈值,下一部分就会从屏幕底部出现并覆盖当前部分(仍然无法移动)。

初步方法: 将每个部分设置为绝对位置,并通过基于scrollwheel事件更改CSS类来调整它们。正文overflow:hiddentransform属性可以操纵各个部分。不过,我正在讨论问题。

  1. 滚动事件似乎被记录为非常不稳定的解决方案。
  2. 事件的.wheelDelta方面异步触发,很难捕获手势。 (在chrome上,它只是吐出3倍的倍数而不是px中手势的距离)。这使得难以设置阈值并使响应于该阈值的元素动画化。
  3. 我基本上希望能够跟踪类似滚轮的事件所覆盖的像素数,并将该数字应用于某个滚动提示元素的位置,直到满足滚动阈值。一旦满足,就会激活一个函数来更改类并更新页面上的一些信息。如果不满足阈值,则滚动提示元素返回到其默认位置。

    我所附的方法并不是非常有助于实现这一目标,所以我正在寻找1)一种不同的,更稳定的方法或2)修改/批评我做错了什么用这种方法使其稳定。

    
    
    (function scrollerTest($){
    	$('body').on ('mousewheel', function (e) {
          
    	    var delta = e.originalEvent.wheelDelta,
                currentScreenID = $('section.active').data('self').section_id,
                  currentScreen = $('section.part-' + currentScreenID),
                  nextScreenID = currentScreenID + 1,
                  nextScreen = $('section.part-' + nextScreenID);;
    	
    	    if (delta < 0) { // User is Scrolling Down
              currentScreen.removeClass('active').addClass('top');
              nextScreen.removeClass('bottom').addClass('active')
    	    } else if (delta > 0) { // User is Scrolling Up
    	       
             
    	    }
    	});
    
    }(jQuery));
    &#13;
    body {
      overflow: hidden;
      padding: 0;
      margin: 0;
      }
    section {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100vh;
      z-index: 999;
      background-color: #CA5D44;
      transition: 0.8s all ease-in-out;
      }
    section.part-1 {
      position: relative;
      z-index: 9;
      }
    section.part-2 {
      background-color: #222629;
      }
    section.active {
      transform: translateY(0);
      }
    section.top {
      transform: translateY(-10%);
      }
    section.bottom {
      transform: translateY(100%);
      }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
    
    <body>
      <section class="part-1 home active" data-self='{ "section_id" : 1, "section_title" : "Home", "menu_main_clr" : "#fff" , "menu_second_clr" : "#CA5D44", "logo_clr" : "white" }'>
      </section>
      <section class="part-2 about bottom" data-self='{ "section_id" : 1, "section_title" : "About", "menu_main_clr" : "#CA5D44" , "menu_second_clr" : "#fff", "logo_clr" : "white"  }'>
      </section>
      <section class="part-3 contact bottom" data-self='{ "section_id" : 1, "section_title" : "Contact", "menu_main_clr" : "#fff" , "menu_second_clr" : "#CA5D44", "logo_clr" : "white"  }'>
      </section>
    </body>
    &#13;
    &#13;
    &#13;

    编辑注意: 该片段似乎在触发事件和在第一个实例后更改类时遇到了一些问题 - 不确定原因。在我的本地示例中,它会立即触发它们。

    ** Edite Note 2:** 列出的代码只是我可以实现的最接近行为的副本。不幸的是,这种方法似乎无法实现整个阈值功能,因为轮子事件的行为不像滚动事件。

2 个答案:

答案 0 :(得分:0)

整个滚动主题相当复杂,尤其是当您考虑触摸滚动事件时。 有一些库 - 请参阅此列表,例如:http://ninodezign.com/30-jquery-plugins-for-scrolling-effects-with-css-animation/

之前我使用过https://projects.lukehaas.me/scrollify/,它可能会让你做你想要的事情(最终使用之前的回调),但我不能不自己尝试。另外,与其他库相比,scrollify相对较大(缩小了8kb)。

答案 1 :(得分:0)

您可以通过确保每个内容填充的部分后跟空白透明间隙(在下面的示例中,高度也为100vh)然后使用javascript将position:fixed应用于每个内容填充部分,当它到达视口顶部时。

示例:

&#13;
&#13;
var screens = document.getElementsByClassName('screen');

function checkPosition() {

	for (var i = 0; i < (screens.length - 1); i++) {
	    var topPosition = screens[i].getBoundingClientRect().top;
    
        if (topPosition < 1) {
            screens[i].style.top = '0';
            screens[i].style.position = 'fixed';
        }
    }
}

window.addEventListener('scroll',checkPosition,false);
&#13;
.screen {
position: absolute;
display: block;
left: 0;
width: 100%;
height: 100vh;
}

.red {
position: fixed;
top: 0;
background-color: rgb(255,0,0);
}

.orange {
top: 200vh;
background-color: rgb(255,140,0);
}

.yellow {
top: 400vh;
background-color: rgb(255,255,0);
}

.green {
top: 600vh;
background-color: rgb(0,191,0);
}

.blue {
top: 800vh;
background-color: rgb(0,0,127);
}

p {
font-size: 20vh;
line-height: 20vh;
text-align: center;
color: rgba(255,255,255,0.4);
}
&#13;
<div class="red screen">
<p>Screen One</p>
</div>

<div class="orange screen">
<p>Screen Two</p>
</div>

<div class="yellow screen">
<p>Screen Three</p>
</div>

<div class="green screen">
<p>Screen Four</p>
</div>

<div class="blue screen">
<p>Screen Five</p>
</div>
&#13;
&#13;
&#13;