sigma
Version:
A JavaScript library dedicated to graph drawing.
271 lines (270 loc) • 10.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var captor_1 = __importStar(require("./captor"));
/**
* Constants.
*/
var DRAG_TIMEOUT = 200;
var DRAGGED_EVENTS_TOLERANCE = 3;
var MOUSE_INERTIA_DURATION = 200;
var MOUSE_INERTIA_RATIO = 3;
var MOUSE_ZOOM_DURATION = 250;
var ZOOMING_RATIO = 1.7;
var DOUBLE_CLICK_TIMEOUT = 300;
var DOUBLE_CLICK_ZOOMING_RATIO = 2.2;
var DOUBLE_CLICK_ZOOMING_DURATION = 200;
/**
* Mouse captor class.
*
* @constructor
*/
var MouseCaptor = /** @class */ (function (_super) {
__extends(MouseCaptor, _super);
function MouseCaptor(container, camera) {
var _this = _super.call(this, container, camera) || this;
// State
_this.enabled = true;
_this.draggedEvents = 0;
_this.downStartTime = null;
_this.lastMouseX = null;
_this.lastMouseY = null;
_this.isMouseDown = false;
_this.isMoving = false;
_this.movingTimeout = null;
_this.startCameraState = null;
_this.clicks = 0;
_this.doubleClickTimeout = null;
_this.currentWheelDirection = 0;
// Binding methods
_this.handleClick = _this.handleClick.bind(_this);
_this.handleRightClick = _this.handleRightClick.bind(_this);
_this.handleDown = _this.handleDown.bind(_this);
_this.handleUp = _this.handleUp.bind(_this);
_this.handleMove = _this.handleMove.bind(_this);
_this.handleWheel = _this.handleWheel.bind(_this);
_this.handleOut = _this.handleOut.bind(_this);
// Binding events
container.addEventListener("click", _this.handleClick, false);
container.addEventListener("contextmenu", _this.handleRightClick, false);
container.addEventListener("mousedown", _this.handleDown, false);
container.addEventListener("mousemove", _this.handleMove, false);
container.addEventListener("wheel", _this.handleWheel, false);
container.addEventListener("mouseout", _this.handleOut, false);
document.addEventListener("mouseup", _this.handleUp, false);
return _this;
}
MouseCaptor.prototype.kill = function () {
var container = this.container;
container.removeEventListener("click", this.handleClick);
container.removeEventListener("contextmenu", this.handleRightClick);
container.removeEventListener("mousedown", this.handleDown);
container.removeEventListener("mousemove", this.handleMove);
container.removeEventListener("wheel", this.handleWheel);
container.removeEventListener("mouseout", this.handleOut);
document.removeEventListener("mouseup", this.handleUp);
};
MouseCaptor.prototype.handleClick = function (e) {
var _this = this;
if (!this.enabled)
return;
this.clicks++;
if (this.clicks === 2) {
this.clicks = 0;
if (typeof this.doubleClickTimeout === "number") {
clearTimeout(this.doubleClickTimeout);
this.doubleClickTimeout = null;
}
return this.handleDoubleClick(e);
}
setTimeout(function () {
_this.clicks = 0;
_this.doubleClickTimeout = null;
}, DOUBLE_CLICK_TIMEOUT);
// NOTE: this is here to prevent click events on drag
if (this.draggedEvents < DRAGGED_EVENTS_TOLERANCE)
this.emit("click", captor_1.getMouseCoords(e));
};
MouseCaptor.prototype.handleRightClick = function (e) {
if (!this.enabled)
return;
this.emit("rightClick", captor_1.getMouseCoords(e));
};
MouseCaptor.prototype.handleDoubleClick = function (e) {
if (!this.enabled)
return;
var newRatio = this.camera.getState().ratio / DOUBLE_CLICK_ZOOMING_RATIO;
this.camera.animate(this.camera.getViewportZoomedState({ x: captor_1.getX(e), y: captor_1.getY(e) }, {
width: this.container.offsetWidth,
height: this.container.offsetHeight,
}, newRatio), {
easing: "quadraticInOut",
duration: DOUBLE_CLICK_ZOOMING_DURATION,
});
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
e.stopPropagation();
return false;
};
MouseCaptor.prototype.handleDown = function (e) {
if (!this.enabled)
return;
this.startCameraState = this.camera.getState();
this.lastMouseX = captor_1.getX(e);
this.lastMouseY = captor_1.getY(e);
this.draggedEvents = 0;
this.downStartTime = Date.now();
// TODO: dispatch events
switch (e.which) {
default:
// Left button pressed
this.isMouseDown = true;
this.emit("mousedown", captor_1.getMouseCoords(e));
}
};
MouseCaptor.prototype.handleUp = function (e) {
var _this = this;
if (!this.enabled || !this.isMouseDown)
return;
this.isMouseDown = false;
if (typeof this.movingTimeout === "number") {
clearTimeout(this.movingTimeout);
this.movingTimeout = null;
}
var x = captor_1.getX(e), y = captor_1.getY(e);
var cameraState = this.camera.getState(), previousCameraState = this.camera.getPreviousState();
if (this.isMoving) {
this.camera.animate({
x: cameraState.x + MOUSE_INERTIA_RATIO * (cameraState.x - previousCameraState.x),
y: cameraState.y + MOUSE_INERTIA_RATIO * (cameraState.y - previousCameraState.y),
}, {
duration: MOUSE_INERTIA_DURATION,
easing: "quadraticOut",
});
}
else if (this.lastMouseX !== x || this.lastMouseY !== y) {
this.camera.setState({
x: cameraState.x,
y: cameraState.y,
});
}
this.isMoving = false;
setTimeout(function () { return (_this.draggedEvents = 0); }, 0);
this.emit("mouseup", captor_1.getMouseCoords(e));
};
MouseCaptor.prototype.handleMove = function (e) {
var _this = this;
if (!this.enabled)
return;
this.emit("mousemove", captor_1.getMouseCoords(e));
if (this.isMouseDown) {
// TODO: dispatch events
this.isMoving = true;
this.draggedEvents++;
if (typeof this.movingTimeout === "number") {
clearTimeout(this.movingTimeout);
}
this.movingTimeout = window.setTimeout(function () {
_this.movingTimeout = null;
_this.isMoving = false;
}, DRAG_TIMEOUT);
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight,
};
var eX = captor_1.getX(e), eY = captor_1.getY(e);
var lastMouse = this.camera.viewportToFramedGraph(dimensions, {
x: this.lastMouseX,
y: this.lastMouseY,
});
var mouse = this.camera.viewportToFramedGraph(dimensions, { x: eX, y: eY });
var offsetX = lastMouse.x - mouse.x, offsetY = lastMouse.y - mouse.y;
var cameraState = this.camera.getState();
var x = cameraState.x + offsetX, y = cameraState.y + offsetY;
this.camera.setState({ x: x, y: y });
this.lastMouseX = eX;
this.lastMouseY = eY;
}
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
e.stopPropagation();
return false;
};
MouseCaptor.prototype.handleWheel = function (e) {
var _this = this;
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
e.stopPropagation();
if (!this.enabled)
return false;
var delta = captor_1.getWheelDelta(e);
if (!delta)
return false;
var ratioDiff = delta > 0 ? 1 / ZOOMING_RATIO : ZOOMING_RATIO;
var newRatio = this.camera.getState().ratio * ratioDiff;
var wheelDirection = delta > 0 ? 1 : -1;
var now = Date.now();
// Cancel events that are too close too each other and in the same direction:
if (this.currentWheelDirection === wheelDirection &&
this.lastWheelTriggerTime &&
now - this.lastWheelTriggerTime < MOUSE_ZOOM_DURATION / 5) {
return false;
}
this.camera.animate(this.camera.getViewportZoomedState({ x: captor_1.getX(e), y: captor_1.getY(e) }, {
width: this.container.offsetWidth,
height: this.container.offsetHeight,
}, newRatio), {
easing: "quadraticOut",
duration: MOUSE_ZOOM_DURATION,
}, function () {
_this.currentWheelDirection = 0;
});
this.currentWheelDirection = wheelDirection;
this.lastWheelTriggerTime = now;
return false;
};
MouseCaptor.prototype.handleOut = function () {
// TODO: dispatch event
};
return MouseCaptor;
}(captor_1.default));
exports.default = MouseCaptor;