UNPKG

js-draw

Version:

Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.

145 lines (144 loc) 5.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleSize = exports.HandleAction = void 0; const assertions_1 = require("../../util/assertions"); const math_1 = require("@js-draw/math"); const SelectionTool_1 = require("./SelectionTool"); var HandleShape; (function (HandleShape) { HandleShape[HandleShape["Circle"] = 0] = "Circle"; HandleShape[HandleShape["Square"] = 1] = "Square"; })(HandleShape || (HandleShape = {})); var HandleAction; (function (HandleAction) { HandleAction["ResizeXY"] = "resize-xy"; HandleAction["Rotate"] = "rotate"; HandleAction["ResizeX"] = "resize-x"; HandleAction["ResizeY"] = "resize-y"; })(HandleAction || (exports.HandleAction = HandleAction = {})); // The *interactable* handle size. The visual size will be slightly smaller. exports.handleSize = 30; class SelectionHandle { constructor(presentation, parent, viewport, onDragStart, onDragUpdate, onDragEnd) { this.presentation = presentation; this.parent = parent; this.viewport = viewport; this.onDragStart = onDragStart; this.onDragUpdate = onDragUpdate; this.onDragEnd = onDragEnd; this.dragLastPos = null; this.element = document.createElement('div'); this.element.classList.add(`${SelectionTool_1.cssPrefix}handle`, `${SelectionTool_1.cssPrefix}${presentation.action}`); // Create a slightly smaller content/background element. const visibleContent = document.createElement('div'); visibleContent.classList.add(`${SelectionTool_1.cssPrefix}content`); this.element.appendChild(visibleContent); this.parentSide = presentation.side; const icon = presentation.icon; if (icon) { visibleContent.appendChild(icon); icon.classList.add('icon'); } if (presentation.action === HandleAction.Rotate) { this.shape = HandleShape.Circle; } else { this.shape = HandleShape.Square; } switch (this.shape) { case HandleShape.Circle: this.element.classList.add(`${SelectionTool_1.cssPrefix}circle`); break; case HandleShape.Square: this.element.classList.add(`${SelectionTool_1.cssPrefix}square`); break; default: (0, assertions_1.assertUnreachable)(this.shape); } this.updatePosition(); } /** * Adds this to `container`, where `conatiner` should be the background/selection * element visible on the screen. */ addTo(container) { container.appendChild(this.element); } /** * Removes this element from its container. Should only be called * after {@link addTo}. */ remove() { this.element.remove(); } /** * Returns this handle's bounding box relative to the top left of the * selection box. */ getBBoxParentCoords() { const parentRect = this.parent.getScreenRegion(); const size = math_1.Vec2.of(exports.handleSize, exports.handleSize); const topLeft = parentRect.size .scale(this.parentSide) // Center .minus(size.times(1 / 2)); return new math_1.Rect2(topLeft.x, topLeft.y, size.x, size.y); } /** @returns this handle's bounding box relative to the canvas. */ getBBoxCanvasCoords() { const parentRect = this.parent.region; const size = math_1.Vec2.of(exports.handleSize, exports.handleSize).times(1 / this.viewport.getScaleFactor()); const topLeftFromParent = parentRect.size.scale(this.parentSide).minus(size.times(0.5)); return new math_1.Rect2(topLeftFromParent.x, topLeftFromParent.y, size.x, size.y).translatedBy(parentRect.topLeft); } /** * Moves the HTML representation of this to the location matching its internal representation. */ updatePosition() { const bbox = this.getBBoxParentCoords(); // Position within the selection box. this.element.style.marginLeft = `${bbox.topLeft.x}px`; this.element.style.marginTop = `${bbox.topLeft.y}px`; this.element.style.width = `${bbox.w}px`; this.element.style.height = `${bbox.h}px`; } /** @returns true iff `point` (in editor **canvas** coordinates) is in this. */ containsPoint(point) { const bbox = this.getBBoxCanvasCoords(); const delta = point.minus(bbox.center); // Should have same x and y radius const radius = bbox.size.x / 2; let result; if (this.shape === HandleShape.Circle) { result = delta.magnitude() <= radius; } else { result = Math.abs(delta.x) <= radius && Math.abs(delta.y) <= radius; } return result; } handleDragStart(pointer) { this.onDragStart(pointer.canvasPos); this.dragLastPos = pointer.canvasPos; return true; } handleDragUpdate(pointer) { if (!this.dragLastPos) { return; } this.onDragUpdate(pointer.canvasPos); } handleDragEnd() { if (!this.dragLastPos) { return; } return this.onDragEnd(); } setSnapToGrid(snap) { this.snapToGrid = snap; } isSnappingToGrid() { return this.snapToGrid; } } exports.default = SelectionHandle;