UNPKG

js-draw

Version:

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

84 lines (83 loc) 3.35 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const math_1 = require("@js-draw/math"); const untilNextAnimationFrame_1 = __importDefault(require("../../util/untilNextAnimationFrame")); /** * Automatically scrolls the viewport such that the user's pointer is visible. */ class ToPointerAutoscroller { constructor(viewport, scrollByCanvasDelta) { this.viewport = viewport; this.scrollByCanvasDelta = scrollByCanvasDelta; this.started = false; this.updateLoopId = 0; this.updateLoopRunning = false; this.targetPoint = null; this.scrollRate = 1000; // px/s } getScrollForPoint(screenPoint) { const screenSize = this.viewport.getScreenRectSize(); const screenRect = new math_1.Rect2(0, 0, screenSize.x, screenSize.y); // Starts autoscrolling when the cursor is **outside of** this region const marginSize = 44; const autoscrollBoundary = screenRect.grownBy(-marginSize); if (autoscrollBoundary.containsPoint(screenPoint)) { return math_1.Vec2.zero; } const closestEdgePoint = autoscrollBoundary.getClosestPointOnBoundaryTo(screenPoint); const distToEdge = closestEdgePoint.distanceTo(screenPoint); const toEdge = closestEdgePoint.minus(screenPoint); // Go faster for points further away from the boundary. const maximumScaleFactor = 1.25; const scaleFactor = Math.min(distToEdge / marginSize, maximumScaleFactor); return toEdge.normalizedOrZero().times(scaleFactor); } start() { this.started = true; } onPointerMove(pointerScreenPosition) { if (!this.started) { return; } if (this.getScrollForPoint(pointerScreenPosition) === math_1.Vec2.zero) { this.stopUpdateLoop(); } else { this.targetPoint = pointerScreenPosition; this.startUpdateLoop(); } } stop() { this.targetPoint = null; this.started = false; this.stopUpdateLoop(); } startUpdateLoop() { if (this.updateLoopRunning) { return; } (async () => { this.updateLoopId++; const currentUpdateLoopId = this.updateLoopId; let lastUpdateTime = performance.now(); while (this.updateLoopId === currentUpdateLoopId && this.targetPoint) { this.updateLoopRunning = true; const currentTime = performance.now(); const deltaTimeMs = currentTime - lastUpdateTime; const scrollDirection = this.getScrollForPoint(this.targetPoint); const screenScrollAmount = scrollDirection.times((this.scrollRate * deltaTimeMs) / 1000); this.scrollByCanvasDelta(this.viewport.screenToCanvasTransform.transformVec3(screenScrollAmount)); lastUpdateTime = currentTime; await (0, untilNextAnimationFrame_1.default)(); } this.updateLoopRunning = false; })(); } stopUpdateLoop() { this.updateLoopId++; } } exports.default = ToPointerAutoscroller;