【问题标题】:Fade in content, then animate (flipInX)淡入内容,然后制作动画 (flipInX)
【发布时间】:2016-02-24 02:49:15
【问题描述】:

当我的页面加载时,会显示视口中的内容(不在视图中的内容是容器上的hidden 类)并执行动画(flipInX)。然后当用户向下滚动页面时,hidden 类将从容器中移除,内容淡入淡出(使用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();
      }
    });
  });
});

【问题讨论】:

  • 尝试用.one() 替换.on()
  • @guest271314 将.on() 替换为.one() 会使滚动到视图中的内容无法加载。

标签: javascript jquery css animation


【解决方案1】:

您描述的视觉结果(淡入,然后动画)可以通过仅使用关键帧动画而不依赖 jQuery 的fadeIn 来更好地完成。

我改变了很多东西,并想出了一个非常自然的动画。尽管这可能不是您所期望的,但您可以以此为基础来更接近您想要的结果(同时使用更少的代码)。

这是我改进/改变的:

  • 将检测可见元素的功能替换为更 可靠的方法。 (参考下文)
  • 使用 css animation-state 属性和一点 javascript 来控制每个动画的初始状态和播放
  • 现在将延迟分配给每个滚动条上以前隐藏的元素。
  • 对于淡入淡出部分,我利用了flipInX 中现有的关键帧。您可以在此处调整 opacity 值以获得更好的结果
  • 将一些动画参数从 javascript 移到 CSS。 (例如animation-duration
  • 当flipInX 动画结束时,元素通过animation-fill-mode: forwards 停留在最后一帧。

咨询的来源:

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

带有 cmets 的新代码(更新):

$(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%
}

【讨论】:

  • 哇,好答案!似乎工作得很好,除了页面加载时(在 Safari 上)显示的 .post 元素没有延迟。
  • 我还为最初可见的项目添加了延迟。最重要的是,缺少一些用于 Safari 支持的 -webkit- 前缀,所以我添加了它们。请查看我更新的 anwser 和 fiddle。希望它现在可以更好地工作。
【解决方案2】:

flipInX 动画也在 0% 到 60% 之间为元素的 opacity 设置动画。尝试删除动画中对opacity 的引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 2019-11-30
    • 2015-10-16
    相关资源
    最近更新 更多