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

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

首先是最上面的导航栏,明显的是一个 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 动画效果。