Vue项目监听touch事件实现移动端滑动

        最近需要开发一个前端Web页面,该页面包含多张重叠卡片,卡片可以拖动切换显示顺序,因此需要监听相应事件获取触点信息(滑动开始与结束时触点的Y轴位置)。

        由于该页面实际使用场景在移动端触摸屏,电脑端监听鼠标事件(mouseout、mouseup等)或者拖动事件(dragstart、dragend等)实现的方式在触摸屏上不可用,需要监听touch相关事件(touchstart、touchend)

        由于对touch事件不熟悉,开发过程踩了不少坑,特此记录,以备后续回顾。

        首先在元素上绑定事件监听函数

<template>
    <div @touchstart="touchstart($event)" @touchend="touchend($event)">
        <Card>卡片1</Card>
        <Card>卡片2</Card>
        <Card>卡片3</Card>
    </div>
</template>

        touchstart事件的入参是TouchEvent对象,该对象包含多个参数,其中touchstart事件的触点信息位于TouchEvent对象下的touches数组中,获取touchstart事件发生时触点在Y轴方向位置信息的代码如下

handleTouchStart(el) {
    var pos_start_Y = el.touches[0].clientY
}

        但是touchend事件的触点信息位于TouchEvent对象下的另一个参数中,即changedTouches,所以获取touchend事件发生时触点在Y轴方向位置的代码如下

handleTouchEnd(el) {
    var pos_end_Y = el.changedTouches[0].clientY
}

        通过比对两次触点在Y轴方向的位置信息,就可以判断滑动方向,从而切换相应卡片

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过以下步骤来实现移动端touch事件的横向滑动列表效果并循环展示: 1. 在Vue组件中使用 `v-for` 指令循环渲染列表项,并将每个列表项的宽度设置为屏幕宽度。 2. 使用 `@touchstart`、`@touchmove` 和 `@touchend` 事件监听器来处理用户的触摸事件。 3. 在 `@touchstart` 事件中记录用户触摸的起始位置和时间。 4. 在 `@touchmove` 事件中计算用户触摸的距离和时间,并根据距离和时间的变化计算出列表项应该移动的距离。 5. 在 `@touchend` 事件中根据用户触摸的距离和时间以及列表项的当前位置来计算出列表项应该移动到的位置,并使用动画效果将列表项移动到该位置。 6. 在列表项移动结束后,检查列表项是否已经移动到边界位置,如果已经移动到边界位置,则将列表项的位置重置为循环展示的位置。 下面是一个简单的示例代码: ```html <template> <div class="list-wrapper"> <div class="list-container" ref="listContainer" :style="{ transform: 'translateX(' + x + 'px)' }"> <div v-for="(item, index) in list" :key="index" class="list-item">{{ item }}</div> </div> </div> </template> <script> export default { data() { return { list: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'], screenWidth: document.documentElement.clientWidth, itemWidth: document.documentElement.clientWidth, x: 0, startX: 0, startTime: 0, moveX: 0, moveTime: 0, isMoving: false, }; }, created() { this.itemWidth = this.screenWidth; }, mounted() { this.loopList(); }, methods: { loopList() { const listContainer = this.$refs.listContainer; const firstItem = listContainer.children[0]; const lastItem = listContainer.children[this.list.length - 1]; listContainer.insertBefore(lastItem.cloneNode(true), firstItem); listContainer.appendChild(firstItem.cloneNode(true)); this.x = -this.itemWidth; }, onTouchStart(event) { this.isMoving = true; this.startX = event.touches[0].pageX; this.startTime = Date.now(); }, onTouchMove(event) { this.moveX = event.touches[0].pageX - this.startX; this.moveTime = Date.now() - this.startTime; this.x += this.moveX; this.startX = event.touches[0].pageX; this.startTime = Date.now(); }, onTouchEnd() { this.isMoving = false; const distance = Math.abs(this.moveX); const duration = this.moveTime; const speed = distance / duration; const direction = this.moveX > 0 ? -1 : 1; const threshold = this.itemWidth / 2; let targetX = this.x; if (speed > 0.5 && distance > 30) { targetX += direction * this.itemWidth; } else if (Math.abs(this.moveX) > threshold) { targetX += direction * this.itemWidth; } this.slideTo(targetX); }, slideTo(targetX) { this.x = targetX; const listContainer = this.$refs.listContainer; const duration = 300; const easing = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; listContainer.style.transition = `transform ${duration}ms ${easing}`; listContainer.style.transform = `translateX(${this.x}px)`; setTimeout(() => { listContainer.style.transition = ''; if (this.x <= -this.list.length * this.itemWidth) { this.x = -this.itemWidth; } else if (this.x >= -this.itemWidth) { this.x = -this.list.length * this.itemWidth; } listContainer.style.transform = `translateX(${this.x}px)`; }, duration); }, }, }; </script> <style scoped> .list-wrapper { width: 100%; overflow: hidden; } .list-container { display: flex; width: 100%; transition: transform 300ms cubic-bezier(0.25, 0.1, 0.25, 1.0); } .list-item { width: 100%; height: 100%; box-sizing: border-box; padding: 20px; font-size: 24px; color: #333; } </style> ``` 在这个示例代码中,我们使用 `v-for` 指令循环渲染列表项,将每个列表项的宽度设置为屏幕宽度,使用 `@touchstart`、`@touchmove` 和 `@touchend` 事件监听器处理用户的触摸事件,记录用户触摸的起始位置和时间,在 `@touchmove` 事件中计算用户触摸的距离和时间,并根据距离和时间的变化计算出列表项应该移动的距离,在 `@touchend` 事件中根据用户触摸的距离和时间以及列表项的当前位置来计算出列表项应该移动到的位置,并使用动画效果将列表项移动到该位置,在列表项移动结束后,检查列表项是否已经移动到边界位置,如果已经移动到边界位置,则将列表项的位置重置为循环展示的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值