纯CSS实现小程序导航栏过渡动画
大多数应用中导航栏目是必不可少的组件之一。为导航栏加上选中激活过渡动画也是必不可少的,比如下面效果图中选中导航底部蓝色线条跟随的过渡动画,它是以纯CSS3
实现的。
实现
实现此效果比较简单,定义好导航数据,为导航编写css
样式表,点击选中导航附加选中的样式名。
导航结构和数据
Page({
data: {
navigations: [
{label: '全部', selected: true, value: ''},
{label: '已发布', selected:false, value: 'published'},
{label: '草稿', selected: false, value: 'draft'},
{label: '已下架', selected: false, value: 'expired'},
],
// 默认方向
direction: 'left',
}
});
<view class="headerContainer">
<view class="headerNavigation">
<view bind:tap="onTab" data-index="{{index}}" class="{{item.selected ? 'active active-'+direction : ''}}" wx:for="{{navigations}}"><text>{{item.label}}</text></view>
</view>
</view>
基础CSS
这里使用scss
作为css
预处理器。
.headerContainer {
background-color: var(--weui-BG-2);
position: fixed;
top: 0;
z-index: 1000;
width: 100vw;
.headerNavigation {
width: 100%;
height: 110rpx;
white-space: nowrap;
flex-direction: row;
display: flex;
justify-content: space-between;
view {
padding: 0 20rpx;
position: relative;
color: var(--weui-FG-0);
display: flex;
font-size: 32rpx;
align-items: center;
}
}
}
选中和过渡动画
为导航增加选中的css
和选中的过渡动画css
。
- 选中CSS
.active {
font-weight: 700;
color: var(--weui-BRAND) !important;
}
.active::after {
content: " ";
width: 24px;
height: 4px;
position: absolute;
background-color: var(--weui-BRAND);
bottom: 0;
left: calc(50% - 12px);
text-align: center;
border-radius: 2px;
}
- 过渡动画
使用css3
的animation
实现过渡动画。
/*从左向右跟随*/
.active-left::after {
animation: slideLeftToRight ease .3s forwards;
}
/*从右向左跟随*/
.active-right::after {
animation: slideRightToLeft ease .3s forwards;
}
@keyframes slideLeftToRight {
from {
transform: translate3d(-100%, 0, 0);
}
to {
transform: translate3d(0, 0, 0);
}
}
@keyframes slideRightToLeft {
from {
transform: translate3d(100%, 0, 0);
}
to {
transform: translate3d(0, 0, 0);
}
}
选中事件
这里是在微信小程序的实现,为view
标签增加一个bind:tap="onTab"
事件。
...
// 具体实现
onTab(e: WechatMiniprogram.CustomEvent) {
const index = e.currentTarget.dataset.index;
const tabs = this.data.navigations;
if (tabs[index].selected) {
return ;
}
const prevIndex = tabs.findIndex(item => item.selected);
tabs.forEach((element, eIndex) => {
element.selected = false;
if (index == eIndex) {
element.selected = true;
}
});
this.setData({
navigations: tabs,
direction: index > prevIndex ? 'left' : 'right',
});
},
...