0

所以我使用 React/ PoseShowcase来为一个组件制作动画,比如这里看到的Postmates 车队网站

这是一个例子

我快到,但我不知道最后一点。基本上,我有一系列项目:

const chapters = [
  {
    content: "1",
    title: "Create your profile"
  },
  {
    content: "2",
    title: "See their rating"
  },
  {
    content: "3",
    title: "Forgot annoying requests"
  },
  {
    content: "4",
    title: "Block them"
  },
  {
    // tslint:disable-next-line:max-line-length
    content: "5",
    title: "Make your decision"
  },
  {
    content: "6",
    title: "Time elapses"
  },
  {
    content: "7",
    title: "Complete"
  }
];

还有一种handleScroll(e)方法可以做一些事情:

  1. 在组件中滚动时检测
  2. 滚动一章时,它会更新this.state.contentthis.state.title使用正确的章节内容来自chapters

--

// loop through the chapters
for (let index = 0; index < chapters.length; index++) {
  const chapterHeight = componentHeight;
  topOfChapter.push(componentTopY + chapterHeight * index);
  bottomOfChapter.push(componentTopY * 2 + chapterHeight * index);

  // when scrolling through the component
  if (
    scrollY >= component.offsetTop &&
    scrollY <= component.offsetHeight + window.innerHeight
  ) {
    // when scrolling through a chapter
    if (
      scrollY >= topOfChapter[index] &&
      scrollY <= bottomOfChapter[index]
    ) {
      // tslint:disable-next-line:no-console
      console.log(`Scrolling through chapter ${index + 1}`);
      this.setState({
        animate: !this.state.animate,
        content: chapters[index].content,
        title: chapters[index].title
      });
      // tslint:disable-next-line:no-console
      console.log(topOfChapter[index], "topOfChapter[index]");
      // tslint:disable-next-line:no-console
      console.log(bottomOfChapter[index], "bottomOfChapter[index]");
    }
  } else {
    // tslint:disable-next-line:no-console
    console.log("exited the component");
  }
}

问题是我的动画总是在触发,因为this.state.animate滚动时总是在变化。

我只需要在章节更改时触发动画,而不是一直滚动,但我不知道如何。

几个小时前我问了一个问题,它没有动画,但我认为这个问题只有在动画的背景下才真正有意义。

非常感谢任何帮助!

代码沙盒

4

3 回答 3

1

https://codesandbox.io/s/youthful-leftpad-33j4y应该是你要找的效果。

为了让它进入可用状态,我改变了很多东西,并且我必须做出假设。


退出动画完成后,您要开始enter下一章的动画。您遇到的问题是,您已经忘记了上一章,因为您已经更新state到下一章,同时还反复触发动画。

我现在通过跟踪 currentChapter(当前可见的章节)和 nextChapter(您希望过渡到的章节)解决了这个问题。


    <Text
        pose={animate ? "enter" : "exit"}
        onPoseComplete={this.onPoseComplete}
    >

https://popmotion.io/pose/api/posed/#posed-props-onposecomplete

动画完成后,pose将回调 on onPoseComplete。如果动画为假,则将 currentChapter 设置为 nextChapter 例如

当我们退出第 0 章,进入第 1 章时:

{
   animate: false,
   currentChapter: 0,
   nextChapter: 1,
}

这将在 currentChapter 上启动 Exit 动画。当动画完成时,onPoseComplete被调用,如果动画是假的,即退出动画现在已经完成,将状态更新为:

{
   animate: true,
   currentChapter: 1,
   nextChapter: 1,
}

现在将在 currentChapter 上启动enter动画,现在已更改为 1。


现在我们正在跟踪章节索引,我们不需要我删除的title,状态。content

我已将 handleScroll 逻辑简化为我认为等效的逻辑。通过将 scrollY 除以window.innerHeight,我们可以获得您想要显示的章节的索引。


  style={{ height: `${100 * chapters.length}vh` }}

我们知道有多少章,所以只需将章数乘以 100vh

onPoseComplete = () => {

当您使用create-react-app时,您可以使用transform-class-properties它来创建箭头函数,而不是.bind.

于 2019-11-24T00:16:13.813 回答
0

您应该缓存章节的位置,方法是将其保存为组件状态的数组,仅当页面加载来自数据库的章节数据以及用户调整屏幕大小时(因为发生这种情况时组件的高度会发生变化)

然后在滚动上将 scrollY 与该章节位置数组进行比较,以确定您所在的位置:

this.state.chapters.forEach( (chapter, index) => {
  if ( scrollY >= chapter.top && scrollY <= chapter.bottom && currentScrolledChapter !== chapter ) {
    currentScrolledChapter = chapter;
  }
});

并根据它的位置进行以下检查:

if ( currentScrolledChapter.title !== this.state.title ) {
  this.setState( {
    animate: !this.state.animate,
    content: chapters[index].content,
    title: chapters[index].title
  } );
}
于 2019-11-23T20:17:22.880 回答
-1

也许你可以使用这个https://www.react-reveal.com/examples/common/Fade

所以你不需要你的自定义实现?

于 2019-11-23T12:08:48.343 回答