手机端touch实现DOM拖拉功能
touch实现DOM拖拉功能
1、面板交互流程图
[ 用户触摸拖动手柄 ]↓
[ 记录起始位置、偏移量 ]↓
[ 实时更新面板 translateY ]↓
[ 手指松开 → 判断释放位置 ]↓
[ 达到恢复条件? → 复位 ]
2、详细实现步骤
2.1 初始面板位置
const initialPosition = () => `translateY(calc(100% - ${CONFIG.INITIAL_VISIBLE}px))`;
panel.style.transform = initialPosition();
-
初始时使用 translateY 将面板往下移动,仅露出 INITIAL_VISIBLE 像素高度。
-
calc(100% - 380px) 表示整个面板往下推到底部,只露出顶部 380px
2.2 触摸事件绑定逻辑
2.2.1 touchstart:开始拖动
const handleTouchStart = (e) => {e.preventDefault();isDragging = true;startY = e.touches[0].clientY;currentTranslateY = getTranslateY(panel);panel.style.transition = 'none';
};
-
禁用默认事件以防页面滚动。
-
记录触摸开始的 Y 坐标。
-
获取当前面板的 Y 位移,供后续增量计算
2.2.2 touchmove:拖动中
const handleTouchMove = (e) => {if (!isDragging) return;e.preventDefault();const currentY = e.touches[0].clientY;const deltaY = currentY - startY;let newY = currentTranslateY + deltaY;if (newY > 20) {panel.style.transform = `translateY(${newY}px)`;} else {handleTouchEnd(); // 拖得太高,触发重置逻辑}
};
-
计算拖动偏移量 deltaY。
-
当新的 Y 值小于 20(用户往上推太多)时自动触发 handleTouchEnd,避免面板移动到看不见
2.2.3 touchend:松手后处理
const handleTouchEnd = () => {if (!isDragging) return;isDragging = false;panel.style.transition = 'transform 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28)';const currentY = getTranslateY(panel);if (currentY > (panelHeight - CONFIG.INITIAL_VISIBLE) * (1 - CONFIG.RECOVER_THRESHOLD)) {resetPanel();};
};
-
检查拖动终点位置是否低于恢复阈值。
-
若是,则自动将面板复位(translateY(calc(100% - 380px)))
2.3 工具函数:获取当前 Y 偏移
const getTranslateY = (element) => {const matrix = new DOMMatrix(getComputedStyle(element).transform);return matrix.m42;
};
-
通过 CSS transform: translateY(…) 得到当前 Y 偏移值。
-
DOMMatrix 可以解析 transform 字符串,m42 就是 Y 坐标
2.4 窗口尺寸变化时自动复位
window.addEventListener('resize', () => {panelHeight = panel.offsetHeight;resetPanel();
});
- 页面尺寸改变(如手机旋转)时重新计算面板高度并复位面板。
2.5 注册事件监听器
document.addEventListener('touchmove', handleTouchMove, { passive: false });
document.addEventListener('touchend', handleTouchEnd, false);
dragHandle.addEventListener('touchstart', handleTouchStart, false);
dragHandle.addEventListener('click', resetPanel);
-
所有拖动逻辑只在 dragHandle 上生效,避免误操作。
-
监听文档层级的 touchmove 和 touchend,确保拖动时不会漏掉事件