用weex的DOM模块和BindingX获取节点信息并制作动画效果
下方实例是用了uniapp的uni-nav-bar 组件(uniapp编译模式),控制下划线移动的动画效果
<template>
<view>
<uni-nav-bar :statusBar="true" :fixed="true" class="w-100" :border="false">
<view slot='left' class="pl-2" @click="showDrawer('showLeft')">
<text class="textfff iconfont font-lg"></text>
</view>
<view ref="tabList" style="margin-left:20rpx;margin-right:70rpx" class='flex align-center justify-between font-weight-bold flex-1 position-relative'>
<text class='textfff font-weight-bold' style="font-size:14px;" v-for="(item,index) in tabBars" :key="index" :class="tabindex===index?'':''" @click="changeTab(index)">{{item.name}}</text>
<!-- 动画控制下滑线移动 -->
<view ref="tabLine" class="position-absolute" style="bottom: -10px;left:5px;">
<text class='textfff'>__</text>
</view>
</view>
<view slot='right' class="pr-0" @click="confirmShare">
<text class="textfff iconfont font-lg"></text>
</view>
</uni-nav-bar>
</view>
</template>
<script>
//我的HbuilderX 版本为3.1.4
const BindingX = uni.requireNativePlugin('bindingx');//使用bindingx完成动画,uniapp官方已支持(使用HbuilderX最新版本肯定支持,从HBuilderX 2.3.4起,uni-app 编译模式可直接引用 uni.requireNativePlugin('bindingx') 模块,weex 编译模式还需使用 npm 方式引用。)
const domModule = weex.requireModule('dom'); //使用weex的dom模块
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue' //引入uniapp官方组件uniNavBar,我没有用easycom 模式
export default {
components:{
//注册组件
uniNavBar
},
data() {
return {
tabindex:0,
tabBars:[
{
'name':'发现'
},
{
'name':'案例'
},
{
'name':'质保'
}
],
tabMove:0,//动画起始位置
earyMove:0,//动画移动距离
}
},
created() {
//引入阿里字体图标库
domModule.addRule('fontFace', {
'fontFamily': 'iconfont',
'src': "url(\'https://at.alicdn.com/t/'你的字体'.ttf\')"
})
},
onReady(e){
let element = this.getEl(this.$refs.tabList)
domModule.getComponentRect(element,(ret)=>{
console.log(ret);
//渲染完成后获取节点DOM信息,用于计算动画每次的移动距离
this.earyMove = ((ret.size.width-30)/2).toFixed(2)
});
},
watch:{
//监听home页面顶部选项卡切换,我这里配合swiper 切换页面,只需要监听tabindex变化执行动画,但是动画是在swiper切换完成后才开始,所以也可以监听swiper的滑动距离完善更好的动画效果哦(我就不完善了)
tabindex:function(index){
console.log(index)
console.log(this.earyMove)
console.log(this.tabMove)
let main_image = this.getEl(this.$refs.tabLine)
let move
switch(index){
case 0:
if(this.tabMove>this.earyMove){
//从第三个回来
move = -(parseInt(this.earyMove))*2
}else if(this.tabMove = this.earyMove){
//从第二个回来
move = -parseInt(this.earyMove)
}else{
//重复点击了第一个
return
}
break;
case 1:
if(this.tabMove>this.earyMove){
//从第三个回来
move = -parseInt(this.earyMove)
}else{
//从第一个过来
move = parseInt(this.earyMove)
}
break;
case 2:
if(this.tabMove==0){
//从第一个右移
move = parseInt(this.earyMove)*2
}else if(this.tabMove = this.earyMove){
//从第二个右移
move = parseInt(this.earyMove)
}else{
//重复点击第三个
return
}
break;
}
//使用bindingx开始动画效果
let main_binding = BindingX.bind({
eventType: 'timing', //动画,bindingx还支持手势,滚动,陀螺仪
props: [{
element: main_image, //$refs
property: 'transform.translateX', //动画类型
expression: 'easeOutCubic(t,'+this.tabMove+','+move+',300)' //用了差值器,详见bindingX文档,内置30多个差值器
}]
},(res)=>{
if (res.state === 'exit') {
//动画结束,解除绑定
BindingX.unbind({
token: main_binding.token,
eventType: 'timing'
})
}
});
//动画完成重置起始点
switch(index){
case 0:
this.tabMove = 0
break;
case 1:
this.tabMove = parseInt(this.earyMove)
break;
case 2:
this.tabMove = parseInt(this.earyMove)*2
break;
}
}
},
methods: {
//获取$refs
getEl(el){
if (typeof el === 'string' || typeof el === 'number') return el;
if (WXEnvironment) {
return el.ref;
} else {
return el instanceof HTMLElement ? el : el.$el;
}
},
//home页面--点击上方tabbar功能按钮
changeTab(index){
this.tabindex = index
},
}
}
</script>
<style>
//使用阿里矢量图库
.iconfont {
font-family: iconfont!important;
}
</style>