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
JavaScript
"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;