【问题标题】:Parallax content in a horizontal ScrollMagic container per slide is stuttered每张幻灯片的水平 ScrollMagic 容器中的视差内容结结巴巴
【发布时间】:2019-08-28 22:21:33
【问题描述】:

我有一个固定滑块,当您通过更新内部包装器的X 值到达它时,它会水平移动。这部分效果很好。

但是,对于每张单独的幻灯片,我希望为文本添加视差效果(滚动时变慢 - 相对于当前幻灯片)。

这是我设置的一个小型(简化)测试用例: https://codepen.io/michaelpumo/pen/EJgWgd

不幸的是,由于某种原因,文本似乎交错并且动画不流畅。这可能是因为我误解了 ScrollMagic 的 API(这对我来说是新的)。

我有 2 个控制器,因为我可以获得“视差”部分的唯一方法是将第二个控制器设置为 vertical: false。也许和这个有关?

非常感谢您的帮助!

JavaScript

const ease = window.Power4.easeInOut
const el = document.querySelector('#el')
const wrapper = document.querySelector('#wrapper')
const slides = el.querySelectorAll('.El__slide')
const amount = slides.length
const controller = new window.ScrollMagic.Controller()
const horizontalMovement = new window.TimelineMax()

const controller2 = new window.ScrollMagic.Controller({
  vertical: false
})

horizontalMovement
  .add([
    window.TweenMax.to(wrapper, 1, {
      x: `-${(100 / amount) * (amount - 1)}%`
    })
  ])

new window.ScrollMagic.Scene({
    triggerElement: el,
    triggerHook: 'onLeave',
    duration: `${amount * 100}%`
  })
  .setPin(el)
  .setTween(horizontalMovement)
  .addTo(controller)

slides.forEach((item, index) => {
  const title = item.querySelector('h1')
  const subtitle = item.querySelector('h2')
  const tween = new window.TimelineMax()

  tween
    .fromTo(title, 1, { x: 0 }, { x: 500 }, 0)
    .fromTo(subtitle, 1, { x: 600 }, { x: 500 }, 0)

  new window.ScrollMagic.Scene({
      triggerElement: item,
      triggerHook: 1,
      duration: '100%'
    })
    .setTween(tween)
    .addTo(controller2)
})

SCSS

.El {
  width: 100%;
  max-width: 100%;
  overflow: hidden;
  &__wrapper {
    display: flex;
    width: 400vw;
    height: 100vh;
  }
  &__slide {
    display: flex;
    align-items: center;
    width: 100vw;
    padding: 50px;
    &:nth-child(1) {
      background-color: salmon;
    }
    &:nth-child(2) {
      background-color: blue;
    }
    &:nth-child(3) {
      background-color: orange;
    }
    &:nth-child(4) {
      background-color: tomato;
    }
  }
  &__content {
    width: 100%;
  }
  &__title,
  &__subtitle {
    position: relative;
  }
}

HTML

<div id="el" class="El">
  <div id="wrapper" class="El__wrapper">
    <div class="El__slide">
      <div class="El__content">
        <h1 class="El__title">Title A</h1>
        <h2 class="El__subtitle">Subtitle A</h2>
      </div>
    </div>
    <div class="El__slide">
      <div class="El__content">
        <h1 class="El__title">Title B</h1>
        <h2 class="El__subtitle">Subtitle B</h2>
      </div>
    </div>
    <div class="El__slide">
      <div class="El__content">
        <h1 class="El__title">Title C</h1>
        <h2 class="El__subtitle">Subtitle C</h2>
      </div>
    </div>
    <div class="El__slide">
      <div class="El__content">
        <h1 class="El__title">Title D</h1>
        <h2 class="El__subtitle">Subtitle D</h2>
      </div>
    </div>
  </div>
</div>

【问题讨论】:

  • 老实说,那个库有一个大问题。它不支持检查水平可见性。这就是为什么它都破碎和生涩。如果你做了垂直滚动,它可能会正常工作。
  • 好的,谢谢@Deckerz - 你能推荐另一个库来获得同样的效果吗?正如您所说,垂直确实可以正常工作。我很确定我的代码很简单,所以我不知道是不是我错了。
  • 我玩了一个多小时,发现补间同时应用于所有 4 个场景,即使它们是可见的。它只是检测到 scrollY 轴是否相同。
  • 是的,我相信这是故意的。我希望每个补间都与它所在的部分相关。所以我们有一个循环,每个部分都应用一个场景。

标签: javascript css scrollmagic


【解决方案1】:

要使用 ScrollMagic 方法获得所需的效果,您必须将 refreshInterval: 1 设置为控制器 2。

文档:http://scrollmagic.io/docs/ScrollMagic.Controller.html#constructor

示例:https://codepen.io/biomagic/pen/dLgzJO

const ease = window.Power4.easeInOut
const el = document.querySelector('#el')
const wrapper = document.querySelector('#wrapper')
const slides = el.querySelectorAll('.El__slide')
const amount = slides.length
const controller = new window.ScrollMagic.Controller()
const horizontalMovement = new window.TimelineMax()

const controller2 = new window.ScrollMagic.Controller({
  vertical: false,
  refreshInterval: 1
})

horizontalMovement
  .add([
    window.TweenMax.to(wrapper, 1, { x: `-${(100 / amount) * (amount - 1)}%` })
  ])

new window.ScrollMagic.Scene({
  triggerElement: el,
  triggerHook: 'onLeave',
  duration: `${amount * 100}%`
})
  .setPin(el)
  .setTween(horizontalMovement)
  .addTo(controller)

slides.forEach((item, index) => {
  const title = item.querySelector('h1')
  const subtitle = item.querySelector('h2')
  const tween = new window.TimelineMax()
  tween
    .fromTo(title, 1, { x: 0 }, { x: 500 }, 0)
    .fromTo(subtitle, 1, { x: 600 }, { x: 500 }, 0)
  new window.ScrollMagic.Scene({
    triggerElement: item,
    triggerHook: 1,
    duration: '100%'
  })
  .setTween(tween)
  .addTo(controller2)
})

另一种方法。您可以将 tweenChanges: true 添加到您的场景中。

文档:http://scrollmagic.io/docs/animation.GSAP.html#newScrollMagic.Sceneoptions

示例:https://codepen.io/biomagic/pen/rbqpMb

const ease = window.Power4.easeInOut
const el = document.querySelector('#el')
const wrapper = document.querySelector('#wrapper')
const slides = el.querySelectorAll('.El__slide')
const amount = slides.length
const controller = new window.ScrollMagic.Controller()
const horizontalMovement = new window.TimelineMax()

const controller2 = new window.ScrollMagic.Controller({
  vertical: false
})

horizontalMovement
  .add([
    window.TweenMax.to(wrapper, 1, { x: `-${(100 / amount) * (amount - 1)}%` })
  ])

new window.ScrollMagic.Scene({
  triggerElement: el,
  triggerHook: 'onLeave',
  duration: `${amount * 100}%`
})
  .setPin(el)
  .setTween(horizontalMovement)
  .addTo(controller)

slides.forEach((item, index) => {
  const title = item.querySelector('h1')
  const subtitle = item.querySelector('h2')
  const tween = new window.TimelineMax()
  tween
    .fromTo(title, 1, { x: 0 }, { x: 500 }, 0)
    .fromTo(subtitle, 1, { x: 600 }, { x: 500 }, 0)
  new window.ScrollMagic.Scene({
    triggerElement: item,
    triggerHook: 1,
    duration: '100%',
    tweenChanges: true
  })
  .setTween(tween)
  .addTo(controller2)
})

【讨论】:

  • 感谢您提供这些选项。其中,refreshInterval 设置似乎效果最好。您的最后一个示例虽然不起作用并且实际上中断了。 CSS 转换不是一个选项,因为它会转换样式的变化......所以它不会完全坚持用户滚动。我有很多这样的答案,这不是 IMO 的解决方案,更像是一个 hack。我会试试这些。
  • 感谢您的检查。更新了最后一个示例。
  • 我已经交换了第一个和第二个示例,例如来自评论的第二个是最正确的选择。还删除了基于 CSS 过渡选项的第 3 和第 4 个变体,例如不正确。我很高兴这些选项出现了。
  • 在您的两个选项中,我使用了第一个选项 refreshInterval。虽然它并不完美,但它似乎对标题的移动产生了最平滑的效果。感谢您的研究!
【解决方案2】:

我不确定我是否理解您问题的实质。因为我的母语不同。但是,我想帮你。 对于平滑的文本移动,这将帮助您:

.El__title, .El__subtitle {
    position: relative;
    transition-property: all;
    transition-duration: 900ms;
    transition-timing-function: ease;
    transition-delay: 0s;
}

如果我误解了你,请给我举个例子说明你最终需要什么。那我会尽力帮忙的。

【讨论】:

    【解决方案3】:

    我已经测试了你的代码,看起来一切都很好。如果你想要一个平滑的行为来为你的 CSS 添加一个过渡,我可以推荐你。这样你就可以顺利过渡了。

    只需添加以下行:

    &__title,
    &__subtitle {
      position: relative;
    }
    
    /* Add the next lines */
    &__title {
      transition: all .1s linear;
    }
    

    您可以更改效果和时间。我给你发了一个文档链接: Transition DOCS

    【讨论】:

    • 这不是 OP 所要求的
    • 这应该可以修复它说的不平滑的部分,但是 ScrollMagic 的部分,我不清楚预期的结果是什么。我稍后会重读,看看我是否能找到更多信息:)
    • 不,它不会解决任何问题,因为过渡是由 GSAP 应用的,并且会卡顿/卡顿。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2013-01-25
    • 1970-01-01
    • 2015-12-19
    相关资源
    最近更新 更多