chore(navigation): move features to diagram-js
This commit moves the navigation features from bpmn-js to diagram-js so that they can be reused in other modeling / viewer tools. Related to #124 BREAKING CHANGE: Navigation features have been moved to diagram-js. If you use them in custom bundles, update their location accordingly: bpmn-js/lib/features/movecanvas -> diagram-js/lib/navigation/movecanvas bpmn-js/lib/features/zoomscroll -> diagram-js/lib/navigation/zoomscroll bpmn-js/lib/features/touch -> diagram-js/lib/navigation/touch
This commit is contained in:
parent
74900412d0
commit
5a2c5c425c
|
@ -56,16 +56,16 @@ Modeler.prototype.createModdle = function() {
|
|||
Modeler.prototype._interactionModules = [
|
||||
// non-modeling components
|
||||
require('./features/label-editing'),
|
||||
require('./features/zoomscroll'),
|
||||
require('./features/touch'),
|
||||
require('./features/movecanvas')
|
||||
require('diagram-js/lib/navigation/zoomscroll'),
|
||||
require('diagram-js/lib/navigation/movecanvas'),
|
||||
require('diagram-js/lib/navigation/touch')
|
||||
];
|
||||
|
||||
Modeler.prototype._modelingModules = [
|
||||
// modeling components
|
||||
require('bpmn-js-cli'),
|
||||
require('./features/modeling'),
|
||||
require('diagram-js/lib/features/move'),
|
||||
require('./features/modeling'),
|
||||
require('./features/context-pad')
|
||||
];
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
|
||||
function MoveCanvas(events, canvas) {
|
||||
|
||||
var THRESHOLD = 20;
|
||||
|
||||
function init(element) {
|
||||
|
||||
var context = {};
|
||||
|
||||
function getPosition(e) {
|
||||
return { x: e.clientX, y: e.clientY };
|
||||
}
|
||||
|
||||
function getDelta(p1, p2) {
|
||||
return {
|
||||
x: p1.x - p2.x,
|
||||
y: p1.y - p2.y
|
||||
};
|
||||
}
|
||||
|
||||
function isThresholdReached(delta) {
|
||||
return Math.abs(delta.x) > THRESHOLD || Math.abs(delta.y) > THRESHOLD;
|
||||
}
|
||||
|
||||
function cursor(value) {
|
||||
var current = document.body.style.cursor || '';
|
||||
|
||||
if (value !== undefined) {
|
||||
document.body.style.cursor = value;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
function handleMove(event) {
|
||||
|
||||
var position = getPosition(event);
|
||||
|
||||
|
||||
if (!context.dragging && isThresholdReached(getDelta(context.start, position))) {
|
||||
context.dragging = true;
|
||||
|
||||
context.cursor = cursor('move');
|
||||
}
|
||||
|
||||
|
||||
if (context.dragging) {
|
||||
|
||||
var lastPos = context.last || context.start;
|
||||
|
||||
var delta = getDelta(position, lastPos);
|
||||
|
||||
canvas.scroll({
|
||||
dx: delta.x,
|
||||
dy: delta.y
|
||||
});
|
||||
|
||||
context.last = position;
|
||||
}
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
|
||||
function handleEnd(event) {
|
||||
$(element).off('mousemove', handleMove);
|
||||
$(document).off('mouseup', handleEnd);
|
||||
|
||||
if (context) {
|
||||
cursor(context.cursor);
|
||||
}
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function handleStart(event) {
|
||||
|
||||
var position = getPosition(event);
|
||||
|
||||
context = {
|
||||
start: position
|
||||
};
|
||||
|
||||
$(element).on('mousemove', handleMove);
|
||||
$(document).on('mouseup', handleEnd);
|
||||
|
||||
// prevent select
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
$(element).on('mousedown', handleStart);
|
||||
}
|
||||
|
||||
events.on('canvas.init', function(e) {
|
||||
init(e.paper.node);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
MoveCanvas.$inject = [ 'eventBus', 'canvas' ];
|
||||
|
||||
module.exports = MoveCanvas;
|
|
@ -1,4 +0,0 @@
|
|||
module.exports = {
|
||||
__init__: [ 'moveCanvas' ],
|
||||
moveCanvas: [ 'type', require('./MoveCanvas') ]
|
||||
};
|
|
@ -1,198 +0,0 @@
|
|||
'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;
|
|
@ -1,7 +0,0 @@
|
|||
module.exports = {
|
||||
__depends__: [
|
||||
require('diagram-js/lib/features/touch')
|
||||
],
|
||||
__init__: [ 'touchInteraction' ],
|
||||
touchInteraction: [ 'type', require('./TouchInteraction') ]
|
||||
};
|
|
@ -1,90 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var $ = require('jquery');
|
||||
|
||||
var mousewheel = require('jquery-mousewheel');
|
||||
if (mousewheel !== $ && !$.mousewheel) { mousewheel($); }
|
||||
|
||||
|
||||
function ZoomScroll(events, canvas) {
|
||||
|
||||
var RANGE = { min: 0.2, max: 4 };
|
||||
|
||||
var ZOOM_OFFSET = 5;
|
||||
var SCROLL_OFFSET = 50;
|
||||
|
||||
function cap(scale) {
|
||||
return Math.max(RANGE.min, Math.min(RANGE.max, scale));
|
||||
}
|
||||
|
||||
function reset() {
|
||||
canvas.zoom('fit-viewport');
|
||||
}
|
||||
|
||||
function zoom(direction, position) {
|
||||
|
||||
var currentZoom = canvas.zoom();
|
||||
var factor = 1 + (direction / ZOOM_OFFSET);
|
||||
|
||||
canvas.zoom(cap(currentZoom * factor), position);
|
||||
}
|
||||
|
||||
|
||||
function init(element) {
|
||||
|
||||
$(element).on('mousewheel', function(event) {
|
||||
|
||||
var shift = event.shiftKey,
|
||||
ctrl = event.ctrlKey;
|
||||
|
||||
var x = event.deltaX,
|
||||
y = event.deltaY;
|
||||
|
||||
if (shift || ctrl) {
|
||||
var delta = {};
|
||||
|
||||
if (ctrl) {
|
||||
delta.dx = SCROLL_OFFSET * x;
|
||||
} else {
|
||||
delta.dy = SCROLL_OFFSET * x;
|
||||
}
|
||||
|
||||
canvas.scroll(delta);
|
||||
} else {
|
||||
var offset = {};
|
||||
|
||||
// Gecko Browser should use _offsetX
|
||||
if(!event.originalEvent.offsetX) {
|
||||
offset = {
|
||||
x: event.originalEvent.layerX,
|
||||
y: event.originalEvent.layerY
|
||||
};
|
||||
} else {
|
||||
offset = {
|
||||
x: event.offsetX,
|
||||
y: event.offsetY
|
||||
};
|
||||
}
|
||||
|
||||
// zoom in relative to diagram {x,y} coordinates
|
||||
zoom(y, offset);
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
events.on('canvas.init', function(e) {
|
||||
init(e.paper.node);
|
||||
});
|
||||
|
||||
// API
|
||||
this.zoom = zoom;
|
||||
this.reset = reset;
|
||||
}
|
||||
|
||||
|
||||
ZoomScroll.$inject = [ 'eventBus', 'canvas' ];
|
||||
|
||||
module.exports = ZoomScroll;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
module.exports = {
|
||||
__init__: [ 'zoomScroll' ],
|
||||
zoomScroll: [ 'type', require('./ZoomScroll') ]
|
||||
};
|
|
@ -11,6 +11,7 @@
|
|||
},
|
||||
"keywords": [
|
||||
"bpmn",
|
||||
"bpmn-js",
|
||||
"toolkit",
|
||||
"web modeler",
|
||||
"modeler",
|
||||
|
@ -56,7 +57,6 @@
|
|||
"diagram-js-direct-editing": "^0.3.0",
|
||||
"didi": "^0.0.4",
|
||||
"jquery": "^2.1.0",
|
||||
"jquery-mousewheel": "^3.1.11",
|
||||
"lodash": "^2.4.0",
|
||||
"object-refs": "^0.1.0",
|
||||
"ids": "^0.0.3",
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var Matchers = require('../../../Matchers'),
|
||||
TestHelper = require('../../../TestHelper');
|
||||
|
||||
/* global bootstrapViewer, inject */
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
|
||||
var touchModule = require('../../../../lib/features/touch'),
|
||||
bpmnModule = require('../../../../lib/draw');
|
||||
|
||||
|
||||
describe('features - touch', function() {
|
||||
|
||||
beforeEach(Matchers.addDeepEquals);
|
||||
|
||||
|
||||
var diagramXML = fs.readFileSync('test/fixtures/bpmn/complex.bpmn', 'utf-8');
|
||||
|
||||
var testModules = [ touchModule, bpmnModule ];
|
||||
|
||||
beforeEach(bootstrapViewer(diagramXML, { modules: testModules }));
|
||||
|
||||
|
||||
describe('bootstrap', function() {
|
||||
|
||||
it('should bootstrap', inject(function(touchInteraction) {
|
||||
expect(touchInteraction).not.toBe(null);
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
|
@ -1,38 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var Matchers = require('../../../Matchers'),
|
||||
TestHelper = require('../../../TestHelper');
|
||||
|
||||
/* global bootstrapViewer, inject */
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var $ = require('jquery');
|
||||
|
||||
|
||||
var zoomscrollModule = require('../../../../lib/features/zoomscroll'),
|
||||
bpmnModule = require('../../../../lib/draw');
|
||||
|
||||
|
||||
describe('features - zoomscroll', function() {
|
||||
|
||||
beforeEach(Matchers.addDeepEquals);
|
||||
|
||||
|
||||
var diagramXML = fs.readFileSync('test/fixtures/bpmn/complex.bpmn', 'utf-8');
|
||||
|
||||
var testModules = [ zoomscrollModule, bpmnModule ];
|
||||
|
||||
beforeEach(bootstrapViewer(diagramXML, { modules: testModules }));
|
||||
|
||||
|
||||
describe('bootstrap', function() {
|
||||
|
||||
it('should bootstrap', inject(function(zoomScroll) {
|
||||
expect(zoomScroll).not.toBe(null);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue