SmartBeehive/uni_modules/y-tabs/components/js/touchMixin.js
2024-06-21 18:04:01 +08:00

119 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { getDirection, now } from "./uitls"
export const touchMixin = function() {
return {
data() {
return {
tonchOpt: {
direction: '', //滑动方向
startX: '', //开始滑动的x坐标
startY: '', //开始滑动的y坐标
nextIndex: -1, //下一个切换的标签下标
moved: false, //是否为一次水平滑动
deltaX: 0,
deltaY: 0,
startTimestamp: 0,
nestedSwipeable: true, //对于嵌套的上级tabs是否允许水平滑动下级tabs滑动边界时才允许上级tabs滑动
}
};
},
computed: {
// 是否允许水平滑动
horizontalSwipe() {
return this.swipeable && this.tonchOpt.nestedSwipeable
}
},
created() {
this.nestedTabs = this.getNestedTabs();
},
methods: {
//获取嵌套的上级tabs实例
getNestedTabs(name = 'y-tabs') {
let parent = this.$parent;
let parentName = parent.$options.name;
while (parentName !== name) {
parent = parent.$parent;
if (!parent) return false;
parentName = parent.$options.name;
}
return parent;
},
touchStart(event) {
this.releaseScrollspyLock(); //释放滚动锁
if (!this.horizontalSwipe) return;
this.resetTouchStatus();
this.tonchOpt.startX = event.touches[0].clientX;
this.tonchOpt.startY = event.touches[0].clientY;
this.tonchOpt.startTimestamp = now();
},
touchMove(event) {
if (!this.horizontalSwipe) return;
const touch = event.touches[0];
this.tonchOpt.deltaX = touch.clientX < 0 ? 0 : this.tonchOpt.startX - touch.clientX;
this.tonchOpt.deltaY = this.tonchOpt.startY - touch.clientY;
const offsetX = Math.abs(this.tonchOpt.deltaX);
const offsetY = Math.abs(this.tonchOpt.deltaY);
// 当距离大于某个值时锁定方向
if (!this.tonchOpt.direction || (offsetX < 10 && offsetY < 10)) {
this.tonchOpt.direction = getDirection(offsetX, offsetY);
}
if (this.tonchOpt.direction === "horizontal") { //水平滑动
const { dataLen, contentWidth, currentIndex, tabs, swipeAnimated } = this;
const isRight = this.tonchOpt.deltaX < 0; //判断是否向右滑动
// 如果为第一页,则不允许向右滑;为最后一页,则不允许左滑
if ((isRight && currentIndex === 0) || (!isRight && currentIndex === dataLen - 1)) {
this.setNestTabsSwipe(true)
return;
} else {
this.setNestTabsSwipe(false)
}
this.tonchOpt.nextIndex = currentIndex + (isRight ? -1 : 1); //下一个标签
if (tabs[this.tonchOpt.nextIndex]?.disabled) return; //禁用的标签不允许滑动
this.tonchOpt.moved = true; //标记为一次水平滑动
// 改变标签内容滑动轨道样式,模拟拖动动画效果
if (swipeAnimated) {
const offsetWidth = contentWidth * currentIndex * -1 + offsetX * (isRight ? 1 : -1);
this.changeTrackStyle(true, 0, offsetWidth);
this.setDx(this.tonchOpt.deltaX, false);
}
event.preventDefault(); // 左右滑动时阻止事件继续向上传递,避免触发上下滑动H5端生效
}
},
touchEnd() {
if (this.tonchOpt.moved) {
// 何时可切换标签,当横向滑动距离大于设定阈值,或快速滑动(300ms内)切滑动距离大于18px时
const deltaTime = now() - this.tonchOpt.startTimestamp;
const distance = Math.abs(this.tonchOpt.deltaX);
const speed = (distance / deltaTime).toFixed(4);
const isChange = speed > 0.25 || distance >= Number(this.swipeThreshold); //是否切换
const currIndex = this.currentIndex; //当前选中下标
const targetIndex = isChange ? this.tonchOpt.nextIndex : currIndex; //目标标签的下标
this.touchEndForPane(this.tonchOpt.deltaX, currIndex, targetIndex, isChange);
}
},
// 重置触摸状态
resetTouchStatus() {
this.tonchOpt.direction = '';
this.tonchOpt.deltaX = 0;
this.tonchOpt.deltaY = 0;
this.tonchOpt.nextIndex = -1;
this.tonchOpt.moved = false;
this.tonchOpt.startTimestamp = 0;
this.setNestTabsSwipe(true)
},
// 设置嵌套的上级tabs是否可水平滑动
setNestTabsSwipe(value) {
if (!this.nestedTabs) return;
this.nestedTabs.tonchOpt.nestedSwipeable = value
}
}
}
}