UNPKG

@daign/2d-graphics

Version:

Two dimensional graphics library that implements the daign-2d-pipeline.

167 lines (166 loc) 8.71 kB
"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 __()); }; })(); 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;