bpmn-js/lib/features/touch/TouchInteraction.js

198 lines
4.3 KiB
JavaScript

'use strict';
var $ = require('jquery');
var _ = require('lodash');
function TouchInteraction(eventBus, canvas) {
var context;
var RANGE = { min: 0.2, max: 4 };
var DOUBLE_TAP_THRESHOLD = 300; // ms
function handleTouchStart(event) {
var orgEvent = event.originalEvent ? event.originalEvent : event;
_.forEach(orgEvent.changedTouches, function (touch) {
context.start[touch.identifier] = touch;
});
if (orgEvent.touches.length === 1) {
initMove(orgEvent);
}
if (orgEvent.touches.length === 2) {
initScale(orgEvent);
}
//Stop all interaction for more than 2 touch sources
if (orgEvent.touches.length > 2) {
contextInit();
}
event.preventDefault();
}
function handleTouchMove(event) {
var orgEvent = event.originalEvent;
var cX = 0;
var cY = 0;
var mX = 0;
var mY = 0;
if (context.move && !context.scale) {
_.forEach(orgEvent.changedTouches, function (touch) {
if (touch.identifier === context.moveId) {
cX = touch.clientX;
cY = touch.clientY;
}
});
if (!context.lasttouch.cX) {
context.lasttouch.cX = cX;
}
if (!context.lasttouch.cY) {
context.lasttouch.cY = cY;
}
mX = cX - context.lasttouch.cX;
mY = cY - context.lasttouch.cY;
canvas.scroll({
dx: mX,
dy: mY
});
context.lasttouch.cX = cX;
context.lasttouch.cY = cY;
}
if (context.scale) {
var dist = euclideanDistance(orgEvent.touches[0], orgEvent.touches[1]);
var distRatio = dist / context.start.dist;
zoom(distRatio * context.start.zoom, context.start.mid);
context.lastDistance = dist;
}
// prevent select
event.preventDefault();
}
function handleTouchEnd(event) {
var orgEvent = event.originalEvent;
if (orgEvent.touches.length < 1) {
contextInit();
}
if (orgEvent.touches.length === 1) {
initMove(orgEvent);
}
if (orgEvent.touches.length === 2) {
initScale(orgEvent);
}
_.forEach(orgEvent.changedTouches, function (touch) {
delete context[touch.identifier];
});
// prevent select
event.preventDefault();
}
function init(element) {
contextInit();
//--- general handlers
$(element).on('touchstart', handleTouchStart);
$(element).on('touchmove', handleTouchMove);
$(document).on('touchend', handleTouchEnd);
//--- snap handler
eventBus.on('shape.touchstart', function(event) {
// ---
// TODO must forwarded to touchstart???#
handleTouchStart(event);
});
eventBus.on('shape.touchend', function(event) {
if(event.touches.length !== 0) {
return;
}
if((Date.now() - context.lastTap.time) < DOUBLE_TAP_THRESHOLD) {
eventBus.fire('shape.dbltap', event);
}
context.lastTap.time = Date.now();
});
}
function cap(scale) {
return Math.max(RANGE.min, Math.min(RANGE.max, scale));
}
function zoom(pinchRatio, position) {
canvas.zoom(cap(pinchRatio), position);
}
function euclideanDistance(touch1, touch2) {
var dist =
Math.sqrt(
(touch1.clientX - touch2.clientX) *
(touch1.clientX - touch2.clientX) +
(touch1.clientY - touch2.clientY) *
(touch1.clientY - touch2.clientY)
);
return dist;
}
function initMove(orgEvent) {
context.move = true;
context.moveId = orgEvent.touches[0].identifier;
context.scale = false;
if (!context.lasttouch) {
context.lasttouch = {
cX: undefined,
cY: undefined,
mX: 0,
mY: 0
};
}
}
function initScale(orgEvent) {
context.scale = true;
context.start.dist = euclideanDistance(orgEvent.touches[0], orgEvent.touches[1]);
context.lastDistance = context.start.dist;
context.start.zoom = canvas.zoom();
context.start.mid = {
x: (orgEvent.touches[0].clientX + orgEvent.touches[1].clientX) / 2,
y: (orgEvent.touches[0].clientY + orgEvent.touches[1].clientY) / 2
};
}
function contextInit() {
context = {
start: {},
lastTap: {}
};
}
eventBus.on('canvas.init', function(e) {
init(e.paper.node);
});
}
TouchInteraction.$inject = [ 'eventBus', 'canvas', 'touchFix' ];
module.exports = TouchInteraction;