const actions = require('./base');
const utils = require('../utils');
const InteractEvent = require('../InteractEvent');
const Interactable = require('../Interactable');
const Interaction = require('../Interaction');
const defaultOptions = require('../defaultOptions');
const gesture = {
defaults: {
enabled : false,
origin : null,
restrict: null,
},
checker: function (pointer, event, interactable, element, interaction) {
if (interaction.pointerIds.length >= 2) {
return { name: 'gesture' };
}
return null;
},
getCursor: function () {
return '';
},
};
InteractEvent.signals.on('new', function ({ iEvent, interaction }) {
if (iEvent.type !== 'gesturestart') { return; }
iEvent.ds = 0;
interaction.gesture.startDistance = interaction.gesture.prevDistance = iEvent.distance;
interaction.gesture.startAngle = interaction.gesture.prevAngle = iEvent.angle;
interaction.gesture.scale = 1;
});
InteractEvent.signals.on('new', function ({ iEvent, interaction }) {
if (iEvent.type !== 'gesturemove') { return; }
iEvent.ds = iEvent.scale - interaction.gesture.scale;
interaction.target.fire(iEvent);
interaction.gesture.prevAngle = iEvent.angle;
interaction.gesture.prevDistance = iEvent.distance;
if (iEvent.scale !== Infinity
&& iEvent.scale !== null
&& iEvent.scale !== undefined
&& !isNaN(iEvent.scale)) {
interaction.gesture.scale = iEvent.scale;
}
});
/**
* ```js
* interact(element).gesturable({
* onstart: function (event) {},
* onmove : function (event) {},
* onend : function (event) {},
*
* // limit multiple gestures.
* // See the explanation in {@link Interactable.draggable} example
* max: Infinity,
* maxPerElement: 1,
* });
*
* var isGestureable = interact(element).gesturable();
* ```
*
* Gets or sets whether multitouch gestures can be performed on the target
*
* @param {boolean | object} [options] true/false or An object with event
* listeners to be fired on gesture events (makes the Interactable gesturable)
* @return {boolean | Interactable} A boolean indicating if this can be the
* target of gesture events, or this Interactable
*/
Interactable.prototype.gesturable = function (options) {
if (utils.is.object(options)) {
this.options.gesture.enabled = options.enabled === false? false: true;
this.setPerAction('gesture', options);
this.setOnEvents('gesture', options);
return this;
}
if (utils.is.bool(options)) {
this.options.gesture.enabled = options;
if (!options) {
this.ongesturestart = this.ongesturestart = this.ongestureend = null;
}
return this;
}
return this.options.gesture;
};
InteractEvent.signals.on('set-delta', function ({ interaction, iEvent, action, event, starting, ending, deltaSource }) {
if (action !== 'gesture') { return; }
const pointers = interaction.pointers;
iEvent.touches = [pointers[0], pointers[1]];
if (starting) {
iEvent.distance = utils.touchDistance(pointers, deltaSource);
iEvent.box = utils.touchBBox(pointers);
iEvent.scale = 1;
iEvent.ds = 0;
iEvent.angle = utils.touchAngle(pointers, undefined, deltaSource);
iEvent.da = 0;
}
else if (ending || event instanceof InteractEvent) {
iEvent.distance = interaction.prevEvent.distance;
iEvent.box = interaction.prevEvent.box;
iEvent.scale = interaction.prevEvent.scale;
iEvent.ds = iEvent.scale - 1;
iEvent.angle = interaction.prevEvent.angle;
iEvent.da = iEvent.angle - interaction.gesture.startAngle;
}
else {
iEvent.distance = utils.touchDistance(pointers, deltaSource);
iEvent.box = utils.touchBBox(pointers);
iEvent.scale = iEvent.distance / interaction.gesture.startDistance;
iEvent.angle = utils.touchAngle(pointers, interaction.gesture.prevAngle, deltaSource);
iEvent.ds = iEvent.scale - interaction.gesture.prevScale;
iEvent.da = iEvent.angle - interaction.gesture.prevAngle;
}
});
Interaction.signals.on('new', function (interaction) {
interaction.gesture = {
start: { x: 0, y: 0 },
startDistance: 0, // distance between two touches of touchStart
prevDistance : 0,
distance : 0,
scale: 1, // gesture.distance / gesture.startDistance
startAngle: 0, // angle of line joining two touches
prevAngle : 0, // angle of the previous gesture event
};
});
actions.gesture = gesture;
actions.names.push('gesture');
utils.merge(Interactable.eventTypes, [
'gesturestart',
'gesturemove',
'gestureend',
]);
actions.methodDict.gesture = 'gesturable';
defaultOptions.gesture = gesture.defaults;
module.exports = gesture;