123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- import {
- forEach
- } from 'min-dash';
- import {
- event as domEvent,
- closest as domClosest
- } from 'min-dom';
- import Hammer from 'hammerjs';
- import {
- toPoint
- } from '../../util/Event';
- var MIN_ZOOM = 0.2,
- MAX_ZOOM = 4;
- var mouseEvents = [
- 'mousedown',
- 'mouseup',
- 'mouseover',
- 'mouseout',
- 'click',
- 'dblclick'
- ];
- function log() {
- // console.log.apply(console, arguments);
- }
- function get(service, injector) {
- return injector.get(service, false);
- }
- function stopEvent(event) {
- event.preventDefault();
- event.stopPropagation();
- if (typeof event.stopImmediatePropagation === 'function') {
- event.stopImmediatePropagation();
- }
- }
- function createTouchRecognizer(node) {
- function stopMouse(event) {
- forEach(mouseEvents, function(e) {
- domEvent.bind(node, e, stopEvent, true);
- });
- }
- function allowMouse(event) {
- setTimeout(function() {
- forEach(mouseEvents, function(e) {
- domEvent.unbind(node, e, stopEvent, true);
- });
- }, 500);
- }
- domEvent.bind(node, 'touchstart', stopMouse, true);
- domEvent.bind(node, 'touchend', allowMouse, true);
- domEvent.bind(node, 'touchcancel', allowMouse, true);
- // A touch event recognizer that handles
- // touch events only (we know, we can already handle
- // mouse events out of the box)
- var recognizer = new Hammer.Manager(node, {
- inputClass: Hammer.TouchInput,
- recognizers: []
- });
- var tap = new Hammer.Tap();
- var pan = new Hammer.Pan({ threshold: 10 });
- var press = new Hammer.Press();
- var pinch = new Hammer.Pinch();
- var doubleTap = new Hammer.Tap({ event: 'doubletap', taps: 2 });
- pinch.requireFailure(pan);
- pinch.requireFailure(press);
- recognizer.add([ pan, press, pinch, doubleTap, tap ]);
- recognizer.reset = function(force) {
- var recognizers = this.recognizers,
- session = this.session;
- if (session.stopped) {
- return;
- }
- log('recognizer', 'stop');
- recognizer.stop(force);
- setTimeout(function() {
- var i, r;
- log('recognizer', 'reset');
- for (i = 0; (r = recognizers[i]); i++) {
- r.reset();
- r.state = 8; // FAILED STATE
- }
- session.curRecognizer = null;
- }, 0);
- };
- recognizer.on('hammer.input', function(event) {
- if (event.srcEvent.defaultPrevented) {
- recognizer.reset(true);
- }
- });
- return recognizer;
- }
- /**
- * A plugin that provides touch events for elements.
- *
- * @param {EventBus} eventBus
- * @param {InteractionEvents} interactionEvents
- */
- export default function TouchInteractionEvents(
- injector, canvas, eventBus,
- elementRegistry, interactionEvents) {
- // optional integrations
- var dragging = get('dragging', injector),
- move = get('move', injector),
- contextPad = get('contextPad', injector),
- palette = get('palette', injector);
- // the touch recognizer
- var recognizer;
- function handler(type) {
- return function(event) {
- log('element', type, event);
- interactionEvents.fire(type, event);
- };
- }
- function getGfx(target) {
- var node = domClosest(target, 'svg, .djs-element', true);
- return node;
- }
- function initEvents(svg) {
- // touch recognizer
- recognizer = createTouchRecognizer(svg);
- recognizer.on('doubletap', handler('element.dblclick'));
- recognizer.on('tap', handler('element.click'));
- function startGrabCanvas(event) {
- log('canvas', 'grab start');
- var lx = 0, ly = 0;
- function update(e) {
- var dx = e.deltaX - lx,
- dy = e.deltaY - ly;
- canvas.scroll({ dx: dx, dy: dy });
- lx = e.deltaX;
- ly = e.deltaY;
- }
- function end(e) {
- recognizer.off('panmove', update);
- recognizer.off('panend', end);
- recognizer.off('pancancel', end);
- log('canvas', 'grab end');
- }
- recognizer.on('panmove', update);
- recognizer.on('panend', end);
- recognizer.on('pancancel', end);
- }
- function startGrab(event) {
- var gfx = getGfx(event.target),
- element = gfx && elementRegistry.get(gfx);
- // recognizer
- if (move && canvas.getRootElement() !== element) {
- log('element', 'move start', element, event, true);
- return move.start(event, element, true);
- } else {
- startGrabCanvas(event);
- }
- }
- function startZoom(e) {
- log('canvas', 'zoom start');
- var zoom = canvas.zoom(),
- mid = e.center;
- function update(e) {
- var ratio = 1 - (1 - e.scale) / 1.50,
- newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, ratio * zoom));
- canvas.zoom(newZoom, mid);
- stopEvent(e);
- }
- function end(e) {
- recognizer.off('pinchmove', update);
- recognizer.off('pinchend', end);
- recognizer.off('pinchcancel', end);
- recognizer.reset(true);
- log('canvas', 'zoom end');
- }
- recognizer.on('pinchmove', update);
- recognizer.on('pinchend', end);
- recognizer.on('pinchcancel', end);
- }
- recognizer.on('panstart', startGrab);
- recognizer.on('press', startGrab);
- recognizer.on('pinchstart', startZoom);
- }
- if (dragging) {
- // simulate hover during dragging
- eventBus.on('drag.move', function(event) {
- var originalEvent = event.originalEvent;
- if (!originalEvent || originalEvent instanceof MouseEvent) {
- return;
- }
- var position = toPoint(originalEvent);
- // this gets really expensive ...
- var node = document.elementFromPoint(position.x, position.y),
- gfx = getGfx(node),
- element = gfx && elementRegistry.get(gfx);
- if (element !== event.hover) {
- if (event.hover) {
- dragging.out(event);
- }
- if (element) {
- dragging.hover({ element: element, gfx: gfx });
- event.hover = element;
- event.hoverGfx = gfx;
- }
- }
- });
- }
- if (contextPad) {
- eventBus.on('contextPad.create', function(event) {
- var node = event.pad.html;
- // touch recognizer
- var padRecognizer = createTouchRecognizer(node);
- padRecognizer.on('panstart', function(event) {
- log('context-pad', 'panstart', event);
- contextPad.trigger('dragstart', event, true);
- });
- padRecognizer.on('press', function(event) {
- log('context-pad', 'press', event);
- contextPad.trigger('dragstart', event, true);
- });
- padRecognizer.on('tap', function(event) {
- log('context-pad', 'tap', event);
- contextPad.trigger('click', event);
- });
- });
- }
- if (palette) {
- eventBus.on('palette.create', function(event) {
- var node = event.container;
- // touch recognizer
- var padRecognizer = createTouchRecognizer(node);
- padRecognizer.on('panstart', function(event) {
- log('palette', 'panstart', event);
- palette.trigger('dragstart', event, true);
- });
- padRecognizer.on('press', function(event) {
- log('palette', 'press', event);
- palette.trigger('dragstart', event, true);
- });
- padRecognizer.on('tap', function(event) {
- log('palette', 'tap', event);
- palette.trigger('click', event);
- });
- });
- }
- eventBus.on('canvas.init', function(event) {
- initEvents(event.svg);
- });
- }
- TouchInteractionEvents.$inject = [
- 'injector',
- 'canvas',
- 'eventBus',
- 'elementRegistry',
- 'interactionEvents',
- 'touchFix'
- ];
|