javascript – 淡入内容,然后设置动画(flipInX)

当我的页面加载时,将显示视口中的内容(内容不在视图中获取容器上的隐藏类)并执行动画(flipInX).然后,当用户向下滚动页面时,隐藏的类将从容器中删除,内容淡入(使用fadeIn())到页面上,然后应该执行动画.

我的问题是它正在淡化(fadeIn())到页面上,做动画,然后再次执行fadeIn().

编辑:我发现在一些浏览器(Firefox和Chrome)上它最后会发出额外的“反弹”,而不是第二次消失(Safari)

JSFiddle

HTML

<body class="homepage">
  <main id="main" class="main" role="main" tabindex="-1">
    <div class="main-3">
      <article class="post flipInX animated" data-delay="2">
        <h1 class="h-1">Service 1</h1>
        <div class="entry">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vestibulum, lectus id sollicitudin mattis, quam tortor lobortis orci, sed iaculis mi nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non felis mollis, congue neque eu, rhoncus libero. Nunc ut mattis ante.</div>
      </article>
      <article class="post flipInX animated" data-delay="4">
        <h1 class="h-1">Service 2</h1>
        <div class="entry">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vestibulum, lectus id sollicitudin mattis, quam tortor lobortis orci, sed iaculis mi nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non felis mollis, congue neque eu, rhoncus libero. Nunc ut mattis ante.</div>
      </article>
      <article class="post flipInX animated" data-delay="6">
        <h1 class="h-1">Service 3</h1>
        <div class="entry">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vestibulum, lectus id sollicitudin mattis, quam tortor lobortis orci, sed iaculis mi nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non felis mollis, congue neque eu, rhoncus libero. Nunc ut mattis ante.</div>
      </article>
      <article class="post flipInX animated" data-delay="8">
        <h1 class="h-1">Service 4</h1>
        <div class="entry">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vestibulum, lectus id sollicitudin mattis, quam tortor lobortis orci, sed iaculis mi nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non felis mollis, congue neque eu, rhoncus libero. Nunc ut mattis ante.</div>
      </article>
      <article class="post flipInX animated" data-delay="10">
        <h1 class="h-1">Service 5</h1>
        <div class="entry">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vestibulum, lectus id sollicitudin mattis, quam tortor lobortis orci, sed iaculis mi nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non felis mollis, congue neque eu, rhoncus libero. Nunc ut mattis ante.</div>
      </article>
      <article class="post flipInX animated" data-delay="12">
        <h1 class="h-1">Service 6</h1>
        <div class="entry">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vestibulum, lectus id sollicitudin mattis, quam tortor lobortis orci, sed iaculis mi nulla non ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non felis mollis, congue neque eu, rhoncus libero. Nunc ut mattis ante.</div>
      </article>
    </div>
  </main>
</body>

CSS

* {
  border: 0;
  margin: 0;
  padding: 0;
  -webkit-appearance: none;
  -webkit-border-radius: 0;
}
*,
*:before,
*:after {
  box-sizing: border-box;
}
.hidden {
  visibility: hidden;
}
.main {
  position: relative;
  display: inline-block;
  height: auto;
  width: 98%;
  margin: 40px auto 0 auto;
  text-align: left;
}
.main.minify {
  margin-top: 150px;
}
.main-3 {
  min-height: 400px;
  font-size: 16px;
  line-height: 24px;
}
[class|=h] {
  margin-bottom: 42px;
  font-size: 30px;
  font-weight: normal;
  line-height: 1;
}
.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both
}
.animated.bounceIn,
.animated.bounceOut,
.animated.flipOutX,
.animated.flipOutY {
  -webkit-animation-duration: .75s;
  animation-duration: .75s
}
@-webkit-keyframes flipInX {
  0% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    opacity: 1
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -5deg)
  }
  100% {
    -webkit-transform: perspective(400px);
    transform: perspective(400px)
  }
}
@keyframes flipInX {
  0% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    opacity: 1
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -5deg)
  }
  100% {
    -webkit-transform: perspective(400px);
    transform: perspective(400px)
  }
}
.flipInX {
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
  -webkit-animation-name: flipInX;
  animation-name: flipInX
}
.homepage .main-3 {
  width: 80%;
  margin: 0 auto;
  text-align: center;
}
.homepage .post {
  display: inline-block;
  width: 49%;
  margin-bottom: 40px;
  vertical-align: top;
  -webkit-text-stroke: 0.5px;
}
.homepage .post .h-1 {
  font-size: 26px;
  line-height: 110%;
  margin: 14px 0 10px;
  text-align: center;
}
.homepage .post .entry {
  padding: 0 10%
}

JS

function isScrolledIntoView(elem) {
  var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  var elemTop = $(elem).offset().top;
  var elemBottom = elemTop + $(elem).height();

  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
$(document).ready(function() {
  $('.post').each(function(index) {
    var delay = $(this).attr('data-delay');
    if (typeof delay !== typeof undefined && delay !== false) {
      $(this).css('animation', 'flipInX 2s .' + delay + 's');
      $(this).css('-webkit-animation', 'flipInX 2s .' + delay + 's');
    }
  });
  $('.post').not('.post:first').each(function() {
    if (!isScrolledIntoView($(this))) {
      $(this).addClass('hidden');
    }
  });
  $(document).on('scroll', function() {
    $('.post.hidden').each(function() {
      if (isScrolledIntoView($(this))) {
        $(this).removeClass('hidden').css({
          'display': 'none'
        }).fadeIn();
      }
    });
  });
});

最佳答案 您可以通过仅使用关键帧动画而不依赖于jQuery的fadeIn来更好地完成您描述的视觉效果(淡入,然后设置动画).

我改变了一堆东西,想出了一个非常自然的动画.虽然这可能不是您所期望的,但您可以将其用作接近所需结果的基础(同时使用少量代码).

这是我改进/改变的:

>用更多替换检测可见元素的功能
可靠的方法. (参见下面的参考资料)
>使用css动画状态属性和一些javascript来控制每个动画的初始状态和回放
>延迟现在分配给每个滚动上以前隐藏的元素.
>对于淡入淡出部分,我利用flipInX中的现有关键帧.在那里,您可以调整不透明度值以获得更好的结果
>将一些动画参数从javascript中移出到CSS. (例如动画持续时间)
>当flipInX动画结束时,元素通过使用animation-fill-mode:forwards保持在最后一帧.

消息来源咨询:

> How to tell if a DOM element is visible in the current viewport?
> https://developer.mozilla.org/es/docs/Web/CSS/animation-fill-mode
> https://developer.mozilla.org/es/docs/Web/CSS/animation-play-state

你可以在这个小提琴中看到结果:https://jsfiddle.net/wazaraki/czwrgqdq/

带注释的新代码(更新):

$(function() {
  /** Reccomended technique for detecting visible elements 
      take from https://stackoverflow.com/a/7557433/4405615 
      Removed width detection since we only need the heights */
  function isScrolledIntoView (el) {

    //special bonus for those using jQuery
    if (typeof jQuery === "function" && el instanceof jQuery) {
        el = el[0];
    }

    var rect = el.getBoundingClientRect();

    return (
        rect.top >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) /*or $(window).height() */
    );
}
/* Not longer needed as we now assign delays dinamically on scroll (see below) */
/*  $('.post').each(function(index) {
    var delay = $(this).data('delay');
    if (typeof delay !== typeof undefined && delay !== false) {
      //$(this).css('animation-delay', delay + 's');
      //$(this).css('-webkit-animation-delay', delay + 's');
    }
  });*/
  
  var delay = 0;
  $('.post').each(function() {
    var post = $(this);
    if (isScrolledIntoView(post)) {
      /* start animation for visible elements 
         see the CSS for more info */
      post.css({
          '-webkit-animation-delay': delay + 's',
        	'animation-delay': delay + 's',
        	'webkit-animation-play-state': 'running',
        	'animation-play-state': 'running'
         });
      delay += 0.2;
    } else {
      post.addClass('hidden');
    }
  });
  $(document).on('scroll', function() {
    /** every round starts with 0s delay so following scrolls 
        can start animating immediately */
    var delay = 0;
    $('.post.hidden').each(function() {
      if (isScrolledIntoView(this)) {
        $(this).removeClass('hidden').css({
          '-webkit-animation-delay': delay + 's',
        	'animation-delay': delay + 's',
        	'webkit-animation-play-state': 'running',
        	'animation-play-state': 'running'
         });
        delay += 0.2;
      }
    });
  });
});
* {
  border: 0;
  margin: 0;
  padding: 0;
  -webkit-appearance: none;
  -webkit-border-radius: 0;
}

*,
*:before,
*:after {
  box-sizing: border-box;
}

/** this class doesn't really do anything, just used it for
    marking invisible elements. You could use data
    attributes instead, for example */
.hidden {}

.main {
  position: relative;
  display: inline-block;
  height: auto;
  width: 98%;
  margin: 40px auto 0 auto;
  text-align: left;
}

.main-3 {
  min-height: 400px;
  font-size: 16px;
  line-height: 24px;
}

[class|=h] {
  margin-bottom: 42px;
  font-size: 30px;
  font-weight: normal;
  line-height: 1;
}

.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  /** once the animation finishes we stay on the last
      keyframe */
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@-webkit-keyframes flipInX {
  0% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0;
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  }
  100% {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
    opacity: 1;
  }
}

@keyframes flipInX {
  0% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
    opacity: 0;
  }
  40% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
    -webkit-animation-timing-function: ease-in;
    animation-timing-function: ease-in;
  }
  60% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
    opacity: 1;
  }
  80% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  }
  100% {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
    opacity: 1;
  }
}

.flipInX {
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
  -webkit-animation-name: flipInX;
  animation-name: flipInX;
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
  /* this is a nice way to control animation playback */
  -webkit-animation-play-state: paused;
  animation-play-state: paused;
}

.homepage .main-3 {
  width: 80%;
  margin: 0 auto;
  text-align: center;
}

.homepage .post {
  display: inline-block;
  width: 49%;
  margin-bottom: 40px;
  vertical-align: top;
  -webkit-text-stroke: 0.5px;
  opacity: 0;
}

.homepage .post .h-1 {
  font-size: 26px;
  line-height: 110%;
  margin: 14px 0 10px;
  text-align: center;
}

.homepage .post .entry {
  padding: 0 10%
}
点赞