如何将CSS动画持续时间与滚动绑定

8
我想制作类似于那些网站的效果,您可以向下滚动页面时会出现一些动画效果,如果向上滚动则会反转。我看到了一些库,例如这个,但我想知道是否有更简单的方法来实现这个效果?谢谢。

$(document).ready(function(){
  var lastScrollTop = 0;
    $(document).scroll(function(event){
       var st = $(this).scrollTop();
       if (st > lastScrollTop){
           $('div').removeClass('scrollUp').addClass('scrollDown');
       } else {
          $('div').removeClass('scrollDown').addClass('scrollUp');
       }
       lastScrollTop = st;
    });
});
body{
  height: 150vh;
  overflow-y: auto;
}
div {
    width: 100px;
    height: 100px;
    position: fixed;
}
@keyframes myfirst {
    0%   {background: rgba(0,0,0,0); top: 0px;}
    100% {background: rgba(0,0,0,1); top: 400px;}
}
.scrollDown{
  animation-name: myfirst;
  animation-duration: 5s;
  animation-direction: alternate;
}
.scrollUp{
  animation-name: myfirst;
  animation-duration: 5s;
  animation-direction: alternate-reverse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>

除此之外,我刚刚尝试了通过滚动更改关键帧的方法,使得在向下滚动时100%或动画结束时发生变化,在向上滚动时变为0%,但是它并没有起作用。

 $(document).ready(function(){
  var lastScrollTop = 0;
    $(document).scroll(function(event){
       var st = $(this).scrollTop();
       $('head>style').last().remove();
       if (st > lastScrollTop){
           $('head').append('<style>@keyframes myfirst{0%{background: rgba(0,0,0,0); top: 0px;}100%{background: rgba(0,0,0,1); top: '+st+'px;}}</style>');
           $('div').removeClass('scrollUp').addClass('scrollDown');
       } else {
       $('head').append('<style>@keyframes myfirst{0%{background: rgba(0,0,0,0); top: '+st+'px;}100%{background: rgba(0,0,0,1); top: '+lastScrollTop+'px;}}</style>');
          $('div').removeClass('scrollDown').addClass('scrollUp');
       }
       lastScrollTop = st;
    });
});
body{
  height: 150vh;
  overflow-y: auto;
}
div {
    width: 100px;
    height: 100px;
    position: fixed;
    border: 1px solid black;
}
.scrollDown{
  animation-name: myfirst;
  animation-duration: 0s;
  animation-direction: alternate;
}
.scrollUp{
  animation-name: myfirst;
  animation-duration: 0s;
  animation-direction: alternate-reverse;
}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<div></div>

使用变换解决方案(无关键帧)

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<style> 
body{
  height: 150vh;
  overflow-y: auto;
}
div {
    width: 100px;
    height: 100px;
    position: fixed;
    border: 1px solid black;
    opacity: 0;
    transition: opacity 0s ease;
    background: rgb(0,0,0);
}
</style>
</head>
<body>
<div></div>
<script>
    $(document).ready(function(){
  var lastScrollTop = 0;
    $(document).scroll(function(event){
       var st = $(this).scrollTop();
       $('head>style').last().remove();
       if (st > lastScrollTop){
        
            $('div').css({
                opacity: function() {
                var opacity = ((1 - (400 - st) / 400) * 0.8);
                return opacity;
            }, left: st
        
           });
       } else {
          $('div').css({
                opacity: function() {
                var opacity = ((1 - (400 - st) / 400) * 0.8);
                return opacity;
            }, left: st
        
           });
       }
       lastScrollTop = st;
    });
});
</script>
</body>
</html>


嗨,愚蠢的孩子。我认为,在检测滚动方向后,仅在指定阈值处触发动画是值得尝试的,间隔可能为50至100微秒。 - jidexl21
1个回答

1

可以更简单地完成,而且不需要使用jQuery。这只是一个粗略的方法,但我通过添加容器并传递比率来使其更加通用,以获取大多数完整、有界的从左到右位置和从零到一的不透明度转换:

var locked = false;
var container = document.getElementById('container');
var animated = document.getElementById('animated');

window.addEventListener('scroll', function() {
  if (!locked) {
    window.requestAnimationFrame(function() {

      animated.style.opacity = Math.min(window.scrollY / window.innerHeight, 1);
      animated.style.left = Math.min(animated.style.opacity * container.clientWidth, container.clientWidth - animated.clientWidth).toString() + 'px';

      locked = false; 
    });
  }
  locked = true;
});
#container {
  border: 1px solid red;
  height: 200vh;
  width: 80%;
}

#animated {
  width: 100px;
  height: 100px;
  position: fixed;
  opacity: 0;
  background: rgb(0, 0, 0);
}
<div id="container">
  <div id="animated"></div>
</div>


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