实现手机端滑动导航条,带有弹性回弹效果
<template>
<div>
<div id=”slider” class=”mui-slider”>
<div id=”sliderSegmentedControl” class=”mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted”>
<div class=”mui-scroll”>
<a class=”mui-control-item” :class=”activeNav === index ? \’mui-active\’ : \’\'” v-for=”(item,index) in navList” v-bind:key=”index” @click=”changeActive(index)”>
{{item}}
</a>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
startX: \’\’,
startY: \’\’,
moveEndX: \’\’,
moveEndY: \’\’,
X: \’\’,
Y: \’\’,
muicsroll: undefined,
muislider: undefined,
lastX: 0, //上次所在位置
posX: 0, //最终位置 上次所在位置 + 移动的距离 this.X
navList: [
\’推荐\’,
\’热点\’,
\’北京\’,
\’社会\’,
\’娱乐\’,
\’科技\’,
\’财经\’,
\’体育\’
],
activeNav: 0
}
},
mounted: function() {
this.muicsroll = document.getElementsByClassName(\’mui-scroll\’)[0]
this.muislider = document.getElementsByClassName(\’mui-slider\’)[0]
this.scroll()
},
methods: {
scroll: function() {
this.muicsroll.addEventListener(\’touchstart\’,this.touch,false)
this.muicsroll.addEventListener(\’touchmove\’,this.touch,false)
this.muicsroll.addEventListener(\’touchend\’,this.touch,false)
},
touch: function(ev) {
var ev = ev || window.ev
switch(ev.type){
case \’touchstart\’:
this.startX = ev.touches[0].pageX
this.startY = ev.touches[0].pageY
break;
case \’touchmove\’:
this.moveEndX = ev.changedTouches[0].pageX
this.moveEndY = ev.changedTouches[0].pageY
this.X = this.moveEndX – this.startX
this.Y = this.moveEndY – this.startY
if ( Math.abs(this.X) > Math.abs(this.Y) && this.X > 0 ) {
this.posX = this.X + this.lastX
this.muicsroll.style.transform = “translate3d(“+this.posX+”px,0px,0px)”
this.muicsroll.style.transitionDuration = “0ms”
this.muicsroll.style.transitionTimingFunction = “cubic-bezier(0.165, 0.84, 0.44, 1)”
}
if ( Math.abs(this.X) > Math.abs(this.Y) && this.X < 0 ) {
this.posX = this.X + this.lastX
this.muicsroll.style.transform = “translate3d(“+this.posX+”px,0px,0px)”
this.muicsroll.style.transitionDuration = “0ms”
this.muicsroll.style.transitionTimingFunction = “cubic-bezier(0.165, 0.84, 0.44, 1)”
}
break;
case \’touchend\’:
this.lastX = this.posX
if(this.posX > 0) {
this.muicsroll.style.transitionDuration = “500ms”
this.muicsroll.style.transform = “translate3d(0px,0px,0px)”
this.lastX = 0
}
if(this.posX < -(this.muicsroll.offsetWidth – this.muislider.offsetWidth)) {
this.muicsroll.style.transitionDuration = “500ms”
this.muicsroll.style.transform = “translate3d(“+ (-(this.muicsroll.offsetWidth – this.muislider.offsetWidth)) +”px,0px,0px)”
this.lastX = -(this.muicsroll.offsetWidth – this.muislider.offsetWidth)
}
break;
}
},
changeActive: function(index) {
this.activeNav = index
}
}
}
</script>
<style>
</style>
/*
点击切换选中用vue实现
通过判断最左侧点所在位置 (上次拖动离开后所在位置 + 本次移动的距离) 来进行定位
动画效果 添加transform 属性 参考mui中所添加的动画代码
*/
父子组件传递
父组件:
<template> <div> <nav-scroll :navList="navList" v-on:listenEvent="getActiveIndex"></nav-scroll> </div> </template> <script> import navscroll from \'./NavScroll.vue\' export default { data() { return { navList: [ \'推荐\', \'热点\', \'北京\', \'社会\', \'娱乐\', \'科技\', \'财经\', \'体育\' ] } }, components: { \'nav-scroll\': navscroll }, mounted: function() { }, methods: { getActiveIndex: function(data) { console.log(data) } } } </script> <style> </style>
子组件:
<template> <div> <div id="slider" class="mui-slider"> <div id="sliderSegmentedControl" class="mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted"> <div class="mui-scroll"> <a class="mui-control-item" :class="activeNav === index ? \'mui-active\' : \'\'" v-for="(item,index) in navList" v-bind:key="index" @click="changeActive(index)"> {{item}} </a> </div> </div> </div> </div> </template> <script> export default { data() { return { startX: \'\', startY: \'\', moveEndX: \'\', moveEndY: \'\', X: \'\', Y: \'\', muicsroll: undefined, muislider: undefined, lastX: 0, //上次所在位置 posX: 0, //最终位置 上次所在位置 + 移动的距离 this.X activeNav: 0 } }, props: ["navList"], mounted: function() { this.muicsroll = document.getElementsByClassName(\'mui-scroll\')[0] this.muislider = document.getElementsByClassName(\'mui-slider\')[0] this.scroll() }, methods: { scroll: function() { this.muicsroll.addEventListener(\'touchstart\',this.touch,false) this.muicsroll.addEventListener(\'touchmove\',this.touch,false) this.muicsroll.addEventListener(\'touchend\',this.touch,false) }, touch: function(ev) { var ev = ev || window.ev switch(ev.type){ case \'touchstart\': this.startX = ev.touches[0].pageX this.startY = ev.touches[0].pageY break; case \'touchmove\': this.moveEndX = ev.changedTouches[0].pageX this.moveEndY = ev.changedTouches[0].pageY this.X = this.moveEndX - this.startX this.Y = this.moveEndY - this.startY if ( Math.abs(this.X) > Math.abs(this.Y) && this.X > 0 ) { this.posX = this.X + this.lastX this.muicsroll.style.transform = "translate3d("+this.posX+"px,0px,0px)" this.muicsroll.style.transitionDuration = "0ms" this.muicsroll.style.transitionTimingFunction = "cubic-bezier(0.165, 0.84, 0.44, 1)" } if ( Math.abs(this.X) > Math.abs(this.Y) && this.X < 0 ) { this.posX = this.X + this.lastX this.muicsroll.style.transform = "translate3d("+this.posX+"px,0px,0px)" this.muicsroll.style.transitionDuration = "0ms" this.muicsroll.style.transitionTimingFunction = "cubic-bezier(0.165, 0.84, 0.44, 1)" } break; case \'touchend\': this.lastX = this.posX if(this.posX > 0) { this.muicsroll.style.transitionDuration = "500ms" this.muicsroll.style.transform = "translate3d(0px,0px,0px)" this.lastX = 0 } if(this.posX < -(this.muicsroll.offsetWidth - this.muislider.offsetWidth)) { this.muicsroll.style.transitionDuration = "500ms" this.muicsroll.style.transform = "translate3d("+ (-(this.muicsroll.offsetWidth - this.muislider.offsetWidth)) +"px,0px,0px)" this.lastX = -(this.muicsroll.offsetWidth - this.muislider.offsetWidth) } break; } }, changeActive: function(index) { this.activeNav = index this.$emit(\'listenEvent\',this.activeNav) } } } </script> <style> </style>
效果展示
版权声明:本文为suanmei原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。