学习前端快一年,对css动画方面研究甚少,一直想知道一些常见的动画是怎么实现的,也可以使项目体验变好。
需求:小程序常见的简单带线tab切换,线条滑动动画组件。
实现思路:v-for循环tab项,绝对定位线条,每次点击,运用'transform': 'translateX(**px)',切换位置,在加上一些过渡效果。
难点:点击获得每次移动的距离和线条的长度。
解决方案:运用微信api wx.createSelectorQuery();获得字体元素据左边的距离及每次的移动距离,如图:(不会录动图,效果自己想象吧哈哈哈)
子组件代码
<template>
<div>
<div class="nav_container">
<!-- 线 -->
<div
class="active_bar"
:style="{'background': color, 'transform': 'translateX(' + navOffset + 'px)', 'width': borderWidth + 'px', 'transition-duration': duration + 's'}"
></div>
<div class="nav_item" v-for="(item, index) in nameList" :key="index" @click="chooseTab(item, index)">
<div class="item_text" :id="'nav_'+ index" :style="{'color': currentTab == index ? color : ''}">
{{ item.name }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
nameList: Array,
color: String,
duration: Number
},
data() {
return {
currentTab: 0,
navOffset: 0,
borderWidth: 0,
left: 0
}
},
methods: {
chooseTab(item, index) {
this.currentTab = index;
this.$emit('change', item.id);
this.compoutWidth(index);
},
compoutWidth(index = 0) {
let selectId = `#nav_${index}`;
const query = wx.createSelectorQuery();
query.select(selectId).boundingClientRect(rect => {
this.borderWidth = rect.width;
this.navOffset = rect.left;
}).exec();
}
},
mounted() {
this.$nextTick(() => {
this.compoutWidth();
})
}
}
</script>
<style lang="scss">
.nav_container {
display: flex;
position: relative;
border-bottom: 0;
background-color: #fff;
.active_bar {
position: absolute;
width: 60rpx;
height: 6rpx;
bottom: 0%;
transition: transform .2s cubic-bezier(.645,.045,.355,1);
}
.nav_item {
display: flex;
flex: 1;
font-size: 30rpx;
color: #777777;
line-height: 88rpx;
justify-content: center;
.item_text {
line-height: 88rpx;
}
}
}
</style>
参数含义
nameList:tab切换的项目和绑定的值
nameList: [
{
name: '全部',
id: 0
},
{
name: '待付款',
id: 1
},
{
name: '待发货',
id: 2
},
{
name: '已发货',
id: 3
},
{
name: '已完成',
id: 4
}
],
color:线条颜色
duration:动画完成时长
父组件运用
<my-tabs :nameList="nameList" @change="tabChange" :color="primaryColor" :duration=".2"/>
// change事件
tabChange(value) {
console.log(value, 'value');
}
踩坑
1. 以前写不带动画的tab线条时,用v-if实现每个字后面都有一条线,只是切换显隐状态,所以没有动画效果。要实现动画效果自始至终只有一条线,线条的宽度根据字体元素的宽度而定。看了vant-ui和elementUI的tab切换动画才明白过来的。
2. .exec()没加,获取不到rect的内容。
query.select(selectId).boundingClientRect(rect => {
this.borderWidth = rect.width;
this.navOffset = rect.left;
}).exec();
备注
这个组件非常简单,只是记录自己的学习过程和vantUI他们差的远了,还是要继续学习呀。