vue自定义组件之触屏轮播
程序员文章站
2024-02-05 11:40:16
...
手机上检测touch事件,根据左右滑动实现轮播效果
<template>
<div class="touch_swipe_root" :id="realID"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'customTouchSwipe',
props:{
itemWidthPercent:{
type:Number,
default:100
},
},
data(){
return{
realID:'touchSwipe_',
curIndex:0,
underControl:false,
underFree:false,
lastScreenX:-1,
lastEndScreenX:-1,
childs:[],
lastPos:[],
itemPercent:100
}
},
mounted:function(){
this.realID = "touchSwipe_" + Math.ceil(Math.random()*100000000000)
console.log("get real id", this.realID)
this.$nextTick(()=>{
this.loopChild()
})
},
methods:{
loopChild:function(){
console.log(this.$slots)
var ele = document.getElementById(this.realID)
var child = ele.firstChild
this.childs = []
var index = 0
while(child){
if(1==child.nodeType){
child.classList.add('touch_swipe_item')
this.childs.push(child)
this.lastPos[index] = index
++index
}
child = child.nextSibling
}
console.log("childs", this.childs)
this.processChilds(0)
},
processChilds:function(nowScreenX, isEnd=false){
var min = this.itemWidthPercent
var scrollRatio = 0
var getIndex = this.curIndex
this.childs.forEach((child,index)=>{
var pos = this.getNextPos(index, this.childs.length, this.curIndex)
var boundRatio = (100-this.itemWidthPercent)/2
scrollRatio = (nowScreenX - this.lastScreenX)*this.itemWidthPercent/(window.screen.width*100)
pos = pos + scrollRatio
child.style.left = (pos*this.itemWidthPercent + boundRatio) + "%"
if(Math.abs(pos*this.itemWidthPercent) < min){
min = Math.abs(pos*this.itemWidthPercent)
getIndex = index
}
})
if(isEnd){
if(this.curIndex == getIndex){
if(scrollRatio>0.2){
getIndex-=1
}else if(scrollRatio<-0.2){
getIndex+=1
}
}
var toLeft = scrollRatio<0
var changed = this.curIndex!=getIndex
this.curIndex = getIndex
this.endProcessChilds(0, toLeft, changed)
}
},
endProcessChilds:function(isEnd, toLeft=false, changed=false){
var i = (this.curIndex+this.childs.length)%this.childs.length
this.$emit('touchSwipeChanged', i)
this.underFree = !isEnd
this.childs.forEach((child, index)=>{
var pos = this.getNextPos(index, this.childs.length, this.curIndex)
//console.log("curIndex", this.curIndex, "index", index, "pos", pos)
if(!isEnd){
if(Math.abs(pos - this.lastPos[index])<2){
child.classList.add('moving_swipe_item')
}
if(0==pos){
child.style.zIndex= 999
}
if(toLeft){
if(0==pos || -1==pos){
child.style.visibility = "visible"
}else if(changed){
//child.style.visibility = "hidden"
}
}else{
if(0==pos || 1==pos){
child.style.visibility = "visible"
}else if(changed){
//child.style.visibility = "hidden"
}
}
var boundRatio = (100-this.itemWidthPercent)/2
child.style.left = (pos*this.itemWidthPercent + boundRatio) + "%"
}else{
child.style.zIndex = 0
child.style.visibility = "visible"
child.classList.remove('moving_swipe_item')
this.lastPos[index] = pos
}
})
if(!isEnd){
setTimeout(()=>{
this.endProcessChilds(true, toLeft, changed)
}, 600)
}
},
getNextPos:function(index, count, nextIndex){
nextIndex = (nextIndex + count)%count
if(nextIndex==0 && index+1==count){
return -1
}else if(nextIndex+1==count && 0==index){
return 1;
}
return index - nextIndex
},
touchStart:function(event){
if(event.touches && 1==event.touches.length && false==this.underFree){
//console.log("touch start", event.touches[0].clientY, event.touches[0].pageY, event.touches[0].screenY)
this.underControl = true
this.lastScreenX = event.touches[0].screenX
this.lastEndScreenX = event.touches[0].screenX
}
},
touchMove:function(event){
//console.log("touch move", event)
if(this.underControl && false==this.underFree){
this.processChilds(event.touches[0].screenX)
this.lastEndScreenX = event.touches[0].screenX
event.preventDefault();
}
},
touchEnd:function(event){
//console.log("touch end", event)
if(this.underControl && false==this.underFree){
this.processChilds(this.lastEndScreenX, true)
this.underControl = false
this.lastScreenX = -1
}
}
},
watch:{
itemWidthPercent:function(newVal, oldVal){
console.log("this.itemWidthPercent", newVal)
this.itemWidthPercent = newVal
}
}
}
</script>
<style scoped>
.touch_swipe_root{
position: relative;
}
.touch_swipe_item{
position: absolute;
}
.moving_swipe_item{
transition: left 0.5s ease-out;
}
</style>
注册:
main.js
import customTouchSwipe from './components/customComponent/customTouchSwipe'
Vue.component(customTouchSwipe.name, customTouchSwipe)
使用
<div class="contentArea">
<span class="title">丰富的教学形态,多人音视频实时互动</span>
<customTouchSwipe :itemWidthPercent="swipeItemWidthPercent" class="styleTouchSwipe">
<div class="styleTouchSwipeItem" v-for="(item,index) in styleImages" :key="index">
<div class="styleTouchSwipeItemArea">
<img :src="item.url">
<span>{{index}}:{{item.content}}</span>
</div>
</div>
</customTouchSwipe>
</div>
效果
上一篇: 购物车的设计
下一篇: Qt 之 自定义窗口标题栏