微信小程序-卡地亚首页效果

Database and Ruby, Python, History


设计师不知道怎么找到了卡地亚小程序,说我就要这个效果。。。

这效果妥妥地勾起了我的好奇心。。。

首先是最上面的导航栏,明显的是一个 fixed postion 直接置顶的效果。所以这个都还比较简单。

<View
  className="home-header"
  style=\{\{ paddingTop: `${Taro.getWindowInfo().statusBarHeight}px`,  height: `${Taro.getMenuButtonBoundingClientRect().height + 10}px`, \}\}
>
  zhongxiao37
</View>
.home-header {
  position: fixed;
  top: 0;
  width: 100vw;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  z-index: 1000;
}

还可以看到,当在第一页的时候,是一个透明状态,第二页的时候,是白底。所以根据slice添加不同的 css,以及动画。

需要注意的是,第一页的动画需要一个 300ms 的延迟,因为这背后其实还有一个transform的操作(后面会讲到),且必须用动画,否则画面会抖动。 而第二页的时候,我们就不要这个动画,需要提前出现白底,避免看到第一页的图片的下滑动作(实际上,第一页会下滑一个导航栏高度的记录)。

<View
  className={`home-header ${
    slide === 0 ? "home-header--transparent" : "home-header--solid"
  }`}
  style=\{\{ paddingTop: `${Taro.getWindowInfo().statusBarHeight}px`,  height: `${Taro.getMenuButtonBoundingClientRect().height + 10}px`, \}\}
>
  zhongxiao37
</View>
.home-header {
  position: fixed;
  top: 0;
  width: 100vw;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  z-index: 1000;

  &--transparent {
    background-color: transparent;
    transition: background-color 0.3s ease-in-out;
    transition-delay: 0.3s;
  }

  &--solid {
    background-color: white;
  }
}

接下来是Swiper组件,第一页的时候,不需要额外处理。但是第二页的时候,需要 translateY 一个状态栏的高度。默认加上 300ms 的动画效果,否则画面会抖动。

<Swiper
        className='home-main-swiper'
        style=\{\{
          transform: `${slide === 1 ? `translateY(${Taro.getWindowInfo().statusBarHeight || 0 + Taro.getMenuButtonBoundingClientRect().height + 10}px)` : 'translateY(0)'}`,
        \}\}
        autoplay={false}
        current={0}
        vertical
        scrollWithAnimation
        onTouchEnd={handleTouchEnd}
        onTransition={handleTransition}
      >
.home-main-swiper {
  height: 100vh;
  transition: transform 0.3s;
}

然后是各种事件

首先捕获释放 touch 的事件

const [touchEnd, setTouchEnd] = useState<boolean>(false);
const handleTouchEnd = () => {
  setTouchEnd(true);
};

捕获动画开始事件,设置一个半屏的阈值

const [slide, setSlide] = useState<number>(0);
const halfScreenHeight = screenHeight ? (screenHeight / 4) * 3 : 400;
const handleTransition = (event: any) => {
  if (
    -halfScreenHeight < event.detail.dy &&
    event.detail.dy < halfScreenHeight
  ) {
    return;
  }
  console.log("transition****", event);
  if (touchEnd) {
    if (event.detail.dy < 0) {
      // 向上滑动
      setSlide(0);
    } else {
      // 向下滑动
      setSlide(1);
    }
  }
  console.log("slide****", slide);
};

这样,我们就可以根据 touch 释放的时候,超过阈值就更新slide,然后根据slice设置 css 动画效果。