欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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>

效果

vue自定义组件之触屏轮播

相关标签: Vue