ivue-material-plus
Version:
A high quality UI components Library with Vue.js
145 lines (119 loc) • 3.76 kB
text/typescript
interface Target extends Element {
_touchHandlers?: any;
}
type Handlers = {
left: () => void;
right: () => void;
up: () => void;
down: () => void;
start: () => void;
move: () => void;
end: () => void;
};
// 处理手势
function handleGesture(wrapper) {
const { touchstartX, touchendX, touchstartY, touchendY } = wrapper;
// 用于判断方向边界
const dirRatio = 0.5;
// 用于判断滑动距离是否满足滑动
const minDistance = 16;
// 手指滑动距离
wrapper.offsetX = touchendX - touchstartX;
wrapper.offsetY = touchendY - touchstartY;
// 判断左右滑动
if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
wrapper.left &&
touchendX < touchstartX - minDistance &&
wrapper.left(wrapper);
wrapper.right &&
touchendX > touchstartX + minDistance &&
wrapper.right(wrapper);
}
// 判断上下滑动
if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
wrapper.down &&
touchendY > touchstartY + minDistance &&
wrapper.down(wrapper);
}
}
// 开始
function touchstart(event: TouchEvent, wrapper) {
const touch = event.changedTouches[0];
wrapper.touchstartX = touch.clientX;
wrapper.touchstartY = touch.clientY;
wrapper.start && wrapper.start(Object.assign(event, wrapper));
}
// 结束
function touchend(event: TouchEvent, wrapper) {
const touch = event.changedTouches[0];
wrapper.touchendX = touch.clientX;
wrapper.touchendY = touch.clientY;
wrapper.end && wrapper.end(Object.assign(event, wrapper));
// 处理手势
handleGesture(wrapper);
}
// 移动
function touchmove(event: TouchEvent, wrapper) {
const touch = event.changedTouches[0];
wrapper.touchmoveX = touch.clientX;
wrapper.touchmoveY = touch.clientY;
wrapper.move && wrapper.move(Object.assign(event, wrapper));
}
// 创建事件
function createHandlers(value: Handlers) {
const wrapper = {
touchstartX: 0,
touchstartY: 0,
touchendX: 0,
touchendY: 0,
touchmoveX: 0,
touchmoveY: 0,
offsetX: 0,
offsetY: 0,
left: value.left,
right: value.right,
up: value.up,
down: value.down,
start: value.start,
move: value.move,
end: value.end,
};
return {
touchstart: (e: TouchEvent) => touchstart(e, wrapper),
touchend: (e: TouchEvent) => touchend(e, wrapper),
touchmove: (e: TouchEvent) => touchmove(e, wrapper),
};
}
// 指令定义
function inserted(el: Element, binding: Record<string, any>) {
const value = binding.value;
const target: Target = value.parent ? el.parentElement : el;
const options = value.options || { passive: true };
if (!target) {
return;
}
const handlers = createHandlers(value);
target._touchHandlers = Object(target._touchHandlers);
target._touchHandlers[binding.instance.$.uid] = handlers;
// 添加事件
Object.keys(handlers).forEach((eventName) => {
target.addEventListener(eventName, handlers[eventName], options);
});
}
// 指令与元素解绑时调用
function unbind(el: Element, binding: Record<string, any>) {
const target: Target = binding.value.parent ? el.parentElement : el;
if (!target || !target._touchHandlers) {
return;
}
const handlers = target._touchHandlers[binding.instance.$.uid];
Object.keys(handlers).forEach((eventName) => {
target.removeEventListener(eventName, handlers[eventName]);
});
delete target._touchHandlers[binding.instance.$.uid];
}
export default {
beforeMount: inserted,
unmounted: unbind,
};