49 lines
2.8 KiB
JavaScript
49 lines
2.8 KiB
JavaScript
// Touch adapter for h5/js/swipe-track.js. Pixel offsets stay local to the page;
|
|
// vertical scroll and taps are preserved, including a tap immediately after a drag.
|
|
function finite(value) { return typeof value === 'number' && isFinite(value); }
|
|
function point(event, ending) {
|
|
var touches = event && (ending ? event.changedTouches : event.touches || event.changedTouches);
|
|
if (!touches || touches.length !== 1) return null;
|
|
var touch = touches[0], x = touch.clientX != null ? touch.clientX : touch.pageX;
|
|
var y = touch.clientY != null ? touch.clientY : touch.pageY;
|
|
return finite(x) && finite(y) ? { x: x, y: y, id: touch.identifier } : null;
|
|
}
|
|
function time(event) { return event && finite(event.timeStamp) ? event.timeStamp : Date.now(); }
|
|
function start(event, index, width, count, options) {
|
|
var p = point(event);
|
|
if (!p || !finite(width) || width <= 0 || !finite(index) || !finite(count) || count < 1) return null;
|
|
return { id: p.id, index: index, width: width, count: count, options: options || {},
|
|
x: p.x, y: p.y, lastX: p.x, lastAt: time(event), velocity: 0, horizontal: false, vertical: false };
|
|
}
|
|
function move(state, event) {
|
|
var p = point(event);
|
|
if (!state || !p || p.id !== state.id) return null;
|
|
var dx = p.x - state.x, dy = p.y - state.y, options = state.options;
|
|
if (!state.horizontal && !state.vertical && Math.max(Math.abs(dx), Math.abs(dy)) > (options.startThreshold || 8)) {
|
|
if (Math.abs(dy) * (options.directionRatio || 1) >= Math.abs(dx)) state.vertical = true;
|
|
else state.horizontal = true;
|
|
}
|
|
if (!state.horizontal || state.vertical) return { offset: 0, dragging: false };
|
|
var elapsed = time(event) - state.lastAt;
|
|
if (elapsed > 0) state.velocity = (p.x - state.lastX) / elapsed;
|
|
state.lastX = p.x; state.lastAt = time(event);
|
|
var offset = -state.index * state.width + dx, min = -(state.count - 1) * state.width;
|
|
var limit = options.maxOverscroll == null ? Infinity : options.maxOverscroll;
|
|
if (offset > 0) offset = Math.min(limit, offset * .25);
|
|
else if (offset < min) offset = min - Math.min(limit, (min - offset) * .25);
|
|
return { offset: offset + state.index * state.width, dragging: true };
|
|
}
|
|
function end(state, event, canceled) {
|
|
if (!state) return null;
|
|
var p = point(event, true), next = state.index;
|
|
if (!canceled && p && p.id === state.id && state.horizontal && !state.vertical) {
|
|
var dx = p.x - state.x, speed = time(event) - state.lastAt > 100 ? 0 : state.velocity;
|
|
if (Math.abs(dx) >= Math.min(50, state.width * .2) || (Math.abs(dx) > 12 && Math.abs(speed) > .4)) {
|
|
next = Math.round(state.index - dx / state.width);
|
|
if (next === state.index) next += (Math.abs(speed) > .4 ? speed : dx) < 0 ? 1 : -1;
|
|
}
|
|
}
|
|
return { index: Math.max(0, Math.min(state.count - 1, next)), dragged: state.horizontal };
|
|
}
|
|
module.exports = { start: start, move: move, end: end };
|