You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.7 KiB

import {
INPUT_START,
INPUT_MOVE,
INPUT_END,
INPUT_CANCEL,
INPUT_TYPE_TOUCH
} from '../inputjs/input-consts';
import Input from '../inputjs/input-constructor';
import toArray from '../utils/to-array';
import hasParent from '../utils/has-parent';
import uniqueArray from '../utils/unique-array';
const TOUCH_INPUT_MAP = {
touchstart: INPUT_START,
touchmove: INPUT_MOVE,
touchend: INPUT_END,
touchcancel: INPUT_CANCEL
};
const TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
/**
* @private
* Multi-user touch events input
* @constructor
* @extends Input
*/
export default class TouchInput extends Input {
constructor() {
TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;
super(...arguments);
this.targetIds = {};
// this.evTarget = TOUCH_TARGET_EVENTS;
}
handler(ev) {
let type = TOUCH_INPUT_MAP[ev.type];
let touches = getTouches.call(this, ev, type);
if (!touches) {
return;
}
this.callback(this.manager, type, {
pointers: touches[0],
changedPointers: touches[1],
pointerType: INPUT_TYPE_TOUCH,
srcEvent: ev
});
}
}
/**
* @private
* @this {TouchInput}
* @param {Object} ev
* @param {Number} type flag
* @returns {undefined|Array} [all, changed]
*/
function getTouches(ev, type) {
let allTouches = toArray(ev.touches);
let { targetIds } = this;
// when there is only one touch, the process can be simplified
if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
targetIds[allTouches[0].identifier] = true;
return [allTouches, allTouches];
}
let i;
let targetTouches;
let changedTouches = toArray(ev.changedTouches);
let changedTargetTouches = [];
let { target } = this;
// get target touches from touches
targetTouches = allTouches.filter((touch) => {
return hasParent(touch.target, target);
});
// collect touches
if (type === INPUT_START) {
i = 0;
while (i < targetTouches.length) {
targetIds[targetTouches[i].identifier] = true;
i++;
}
}
// filter changed touches to only contain touches that exist in the collected target ids
i = 0;
while (i < changedTouches.length) {
if (targetIds[changedTouches[i].identifier]) {
changedTargetTouches.push(changedTouches[i]);
}
// cleanup removed touches
if (type & (INPUT_END | INPUT_CANCEL)) {
delete targetIds[changedTouches[i].identifier];
}
i++;
}
if (!changedTargetTouches.length) {
return;
}
return [
// merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
changedTargetTouches
];
}