根据路口观察者复制转场

时间:2019-03-25 21:31:31

标签: javascript html reactjs css-animations intersection-observer

我一直在进行副项目,要求我建立一个网站,周围有一些动画。我选择从React开始(以学习新框架并扩展我的知识)。

我要关注(或试图复制)的一个重要动画来自苹果公司website

当您启动网页并向下滚动时,通过移动60px并更改不透明度可以使文本平滑显示。一旦进入视口。

我试图通过类来做到这一点。但是,我会遇到类问题,因为它们有时会重新渲染我的元素,或者刷新时该组件将不可见。

我还尝试将fadeInsetInterval一起使用,但是,每次激活它的方式都不同。

我使用动画的组件:


import React, { Component } from "react";
import "./SuccessStory.css";

class SuccessStory extends Component {
  state = {
    componentAppearsScrollUp: false,
    componentDisappearsScrollUp: false,
    componentAppearsScrollDown: false,
    componentDisappearsScrollDown: false,
    showComponent: false,
    translateMove: 60,
    opacity: 0
  };

  fadingIn() {
    const timer = setInterval(() => {
      if (this.state.opacity >= 1) {
        clearInterval(timer);
        return;
      }
      this.setState({
        opacity: this.state.opacity + 0.05
      });
    }, 100);
  }

  fadingOut() {
    const timer = setInterval(() => {
      if (this.state.opacity <= 0) {
        clearInterval(timer);
      }
      this.setState({
        opacity: this.state.opacity - 0.05
      });
    }, 100);
  }

  componentDidUpdate(prevProps, prevState) {
    if (this.props.currentY < prevProps.currentY) {
      if (
        this.props.intersectionRatio > prevProps.intersectionRatio &&
        this.props.isIntersecting
      ) {
        if (this.props.intersectionRatio > 0.6) {
          console.log("Scrolling down enter");
          this.fadingIn();
          this.setState({
            componentAppearsScrollUp: false,
            componentDisappearsScrollUp: false,
            componentAppearsScrollDown: true,
            componentDisappearsScrollDown: false,
            showComponent: true
          });
        }
      } else {
        if (
          this.props.intersectionRatio < 0.8 &&
          this.props.intersectionRatio > 0.6
        ) {
          console.log("Scrolling down leave");
          this.setState({
            componentAppearsScrollUp: false,
            componentDisappearsScrollUp: false,
            componentAppearsScrollDown: false,
            componentDisappearsScrollDown: true,
            showComponent: true
          });
          this.fadingOut();
        }
      }
    } else if (
      this.props.currentY > prevProps.currentY &&
      this.props.isIntersecting
    ) {
      if (this.props.intersectionRatio < prevProps.intersectionRatio) {
        if (this.props.intersectionRatio < 0.9) {
          console.log("Scrolling up leave");
          this.fadingOut();
          this.setState({
            componentAppearsScrollUp: false,
            componentDisappearsScrollUp: true,
            componentAppearsScrollDown: false,
            componentDisappearsScrollDown: false,
            showComponent: true
          });
        }
      } else {
        if (
          this.props.intersectionRatio > 0.6 &&
          this.props.intersectionRatio < 0.8
        ) {
          console.log("Scrolling up enter");
          this.setState({
            componentAppearsScrollUp: true,
            componentDisappearsScrollUp: false,
            componentAppearsScrollDown: false,
            componentDisappearsScrollDown: false,
            showComponent: true
          });
          this.fadingIn();
        }
      }
    } else if (
      this.props.isIntersecting &&
      this.props.intersectionRatio > 0.9
    ) {
      this.fadingIn();
    }
  }

  render() {
    return (
      <div
        className={
          (this.state.componentAppearsScrollDown
            ? " story-appear-scroll-down "
            : "") +
          (this.state.componentDisappearsScrollDown
            ? " story-disappear-scroll-down "
            : "") +
          (this.state.componentAppearsScrollUp
            ? "story-appear-scroll-up "
            : "") +
          (this.state.componentDisappearsScrollUp
            ? " story-disappear-scroll-up "
            : "")
        }
        style={{
          opacity: this.state.opacity
        }}
      >
        <h1 className="success-story">The success story</h1>
        <h2
          className="success-story-text-one"
          // style={
          //   this.props.isIntersecting && this.props.intersectionRatio > 0.8
          //     ? { opacity: 1 }
          //     : { opacity: 0 }
          // }
        >
          MobileLife brought together over 100 dedicated people based in
          Copenhagen and Vilnius to deliver innovative mobile solutions to the
          banking customers in Nordic markets.
        </h2>
      </div>
    );
  }
}

export default SuccessStory;

我的父组件将交点观察器值传递给子组件:


import React, { Component } from "react";
import "./SecondPage.css";
import SuccessStory from "./SuccessStory";
import { InView } from "react-intersection-observer";
// import SuccessStoryText1 from "./SuccessStoryText1";
import SuccessStoryText2 from "./SuccessStoryText2";

class SecondPage extends Component {
  state = {
    isIntersecting: false,
    intersectionRatio: "",
    currentY: "",
    isIntersectingSecondText: false,
    intersectionRatioSecondText: "",
    currentYSecondText: ""
  };

  render() {
    return (
      <div className="second-page">
        <div className="navigation-second" style={{ position: "sticky" }} />
        <div style={{ paddingTop: "25%", height: "60vh" }}>
          <InView
            threshold={[0.1, 0.2, 0.3, 0.4, 0.6, 0.75, 0.8]}
            onChange={(inView, ref) => {
              this.setState({
                currentY: ref.boundingClientRect.y,
                isIntersecting: ref.isIntersecting,
                intersectionRatio: ref.intersectionRatio
              });

              // console.log("Inview:", inView, ref);
            }}
          >
            {({ inView, ref }) => (
              <div ref={ref} style={{ position: "sticky", top: "30%" }}>
                <SuccessStory
                  isIntersecting={this.state.isIntersecting}
                  intersectionRatio={this.state.intersectionRatio}
                  currentY={this.state.currentY}
                />
              </div>
            )}
          </InView>
        </div>

        <InView
          threshold={[0.1, 0.2, 0.3, 0.4, 0.6, 0.75, 0.8]}
          onChange={(inView, ref) => {
            if (ref.intersectionRatio > 0.1) {
              this.setState({
                currentYSecondText: ref.boundingClientRect.y,
                isIntersectingSecondText: ref.isIntersecting,
                intersectionRatioSecondText: ref.intersectionRatio
              });
            }
            // console.log("Inview:", inView, ref);
          }}
        >
          {({ inView, ref }) => (
            <div ref={ref}>
              <SuccessStoryText2
                isIntersecting={this.state.isIntersectingSecondText}
                intersectionRatio={this.state.intersectionRatioSecondText}
                currentY={this.state.currentYSecondText}
              />
            </div>
          )}
        </InView>
      </div>
    );
  }
}
//
export default SecondPage;


这是我用来制作动画的CSS:

.story-appear-scroll-down {
  animation: successStoryTextAppearScrollDown 0.3s linear;
  animation-fill-mode: forwards;
}

@keyframes successStoryTextAppearScrollDown {
  from {
    transform: translate3d(0, 60px, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}

.story-disappear-scroll-down {
  animation: successStoryTextDisappearScrollDown 0.3s linear;
  animation-fill-mode: forwards;
}

@keyframes successStoryTextDisappearScrollDown {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}

.story-appear-scroll-up {
  animation: successStoryTextAppearScrollUp 0.3s linear;
  animation-fill-mode: forwards;
}

@keyframes successStoryTextAppearScrollUp {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}

.story-disappear-scroll-up {
  animation: successStoryTextDisappearScrollUp 0.3s linear;
  animation-fill-mode: forwards;
}

@keyframes successStoryTextDisappearScrollUp {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(0, 60px, 0);
  }
}

我在想激活这种动画的正确方法是什么,我试图复制这种动画,并且每次激活它的外观都一样(如Apple网页所示)。但是,由于我已经花了太多时间在此上,所以我无法获得想要的结果。

感谢您的帮助,我们欢迎您提出任何建议或提示,因为这是我的第一篇帖子。

0 个答案:

没有答案