@daign/2d-graphics
Version:
Two dimensional graphics library that implements the daign-2d-pipeline.
167 lines (166 loc) • 8.71 kB
JavaScript
;
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 __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.InteractiveViewport = void 0;
var handle_1 = require("@daign/handle");
var math_1 = require("@daign/math");
var viewport_1 = require("./viewport");
/**
* Group that acts as an interactive viewport by applying a transformation from user input.
*/
var InteractiveViewport = /** @class */ (function (_super) {
__extends(InteractiveViewport, _super);
/**
* Constructor.
* @param context - The target context.
* @param application - The corresponding application.
*/
function InteractiveViewport(context, application) {
var _this = _super.call(this, context, application) || this;
// The object that handles the events on the viewport node.
_this.viewportHandle = undefined;
/**
* Get a vector from the touch position of an event relative to the drawing's context.
* Will throw error when the event does not contain position information.
* @param event - The event to use.
* @param touchIndex - The index of the touch point.
* @returns The resulting vector.
*/
_this.extractFromTouchEventRelativeToContext = function (event, touchIndex) {
if (!_this.context.domNode ||
!_this.context.domNode.getBoundingClientRect) {
throw new Error('Unable to read offset of context node.');
}
// Get the offset of the context node relative to the page.
var rect = _this.context.domNode.getBoundingClientRect();
if (!rect ||
rect.left === undefined ||
rect.top === undefined) {
throw new Error('Unable to read offset of context node.');
}
if (!event ||
!event.touches ||
!event.touches[touchIndex] ||
event.touches[touchIndex].pageX === undefined ||
event.touches[touchIndex].pageY === undefined) {
throw new Error('Unable to extract position from event.');
}
/* Calculate position relative to context node by subtracting the target's offset from the touch
* position on the page. */
var x = event.touches[touchIndex].pageX - rect.left;
var y = event.touches[touchIndex].pageY - rect.top;
return new math_1.Vector2(x, y);
};
if (context.domNode) {
var minimumDragDistance = 5;
var extractFromEvent = function (event) {
return new math_1.Vector2().setFromEventRelative(event);
};
var extractFromTouchEvent = _this.extractFromTouchEventRelativeToContext;
// The object that handles the events on the viewport node.
var handle_2 = new handle_1.MultiTouchScrollHandle();
handle_2.setStartNode(context.domNode);
handle_2.minimumDragDistance = minimumDragDistance;
handle_2.extractFromEvent = extractFromEvent;
handle_2.extractFromTouchEvent = extractFromTouchEvent;
_this.viewportHandle = handle_2;
var transformationSnapshot_1;
handle_2.beginning = function () {
// Save snapshots of center and scale values at drag start.
_this.viewCenter.snap();
_this.viewScale.snap();
transformationSnapshot_1 = _this.transformation.inverseTransformMatrix.clone();
return true;
};
handle_2.continuing = function () {
var startPosition1 = handle_2.getStartPosition(0);
var startPosition2 = handle_2.getStartPosition(1);
var tempPosition1 = handle_2.getTempPosition(0);
var tempPosition2 = handle_2.getTempPosition(1);
var delta1 = handle_2.getDelta(0);
// When there are two positions, then it is a multi touch event. Zoom the viewport.
if (startPosition1 !== undefined && startPosition2 !== undefined &&
tempPosition1 !== undefined && tempPosition2 !== undefined &&
_this.viewCenter.snapshot !== undefined &&
_this.viewScale.snapshot !== undefined) {
// Calculate the distances between the touch points at start and current position.
var distanceStart = startPosition2.clone().sub(startPosition1).length();
var distanceTemp = tempPosition2.clone().sub(tempPosition1).length();
// Distance between touch point should not be zero, should be at least 1.
distanceStart = Math.max(distanceStart, 1);
distanceTemp = Math.max(distanceTemp, 1);
// Zooming by relative distance change between touch points.
var zoomFactor = distanceTemp / distanceStart;
var newScale = _this.viewScale.snapshot.x * zoomFactor;
// Set silent so that updateViewport can be called once at the end.
_this.viewScale.setSilent(newScale);
var transformedTempPosition1 = tempPosition1.clone()
.transform(transformationSnapshot_1);
var transformedstartPosition1 = startPosition1.clone()
.transform(transformationSnapshot_1);
// The new center is calculated so that touch points keep the location that they point to.
var newCenter = _this.viewCenter.snapshot.clone()
.sub(transformedTempPosition1)
.multiplyScalar(1 / zoomFactor)
.add(transformedstartPosition1);
_this.viewCenter.copySilent(newCenter);
}
else if (delta1 !== undefined &&
_this.viewCenter.snapshot !== undefined) {
// When there is one position only, then pan the viewport.
var drag = delta1.clone().multiplyScalar(-1 / _this.viewScale.x);
var newCenter = _this.viewCenter.snapshot.clone().add(drag);
_this.viewCenter.copySilent(newCenter);
}
_this.updateViewport();
_this.application.redraw();
};
// Define action to deactivate element.
handle_2.clicked = function () {
_this.application.selectionManager.setSelection(null, null);
_this.application.redraw();
};
// Define zoom action.
handle_2.scrolling = function () {
var sign = Math.sign(handle_2.scroll.y);
var factor = Math.pow(1.1, -sign);
var oldScale = _this.viewScale.x;
_this.viewScale.setSilent(oldScale * factor);
factor = _this.viewScale.x / oldScale;
var mousePosition = handle_2.scrollPosition.clone();
mousePosition.transform(_this.transformation.inverseTransformMatrix);
var newCenter = _this.viewCenter.clone().sub(mousePosition)
.multiplyScalar(1 / factor).add(mousePosition);
_this.viewCenter.copySilent(newCenter);
_this.updateViewport();
_this.application.redraw();
};
}
return _this;
}
/**
* Enable or disable the viewport actions like panning and zooming.
* @param enabled - Whether to enable or disable the actions.
*/
InteractiveViewport.prototype.enableViewportActions = function (enabled) {
if (this.viewportHandle) {
this.viewportHandle.enabled = enabled;
}
};
return InteractiveViewport;
}(viewport_1.Viewport));
exports.InteractiveViewport = InteractiveViewport;