UNPKG

@tldraw/editor

Version:

tldraw infinite canvas SDK (editor).

110 lines (109 loc) 4.04 kB
import { Vec } from "../../../primitives/Vec.mjs"; import { EASINGS } from "../../../primitives/easings.mjs"; class EdgeScrollManager { constructor(editor) { this.editor = editor; } _isEdgeScrolling = false; _edgeScrollDuration = -1; /** * Update the camera position when the mouse is close to the edge of the screen. * Run this on every tick when in a state where edge scrolling is enabled. * * @public */ updateEdgeScrolling(elapsed) { const { editor } = this; const edgeScrollProximityFactor = this.getEdgeScroll(); if (edgeScrollProximityFactor.x === 0 && edgeScrollProximityFactor.y === 0) { if (this._isEdgeScrolling) { this._isEdgeScrolling = false; this._edgeScrollDuration = 0; } } else { if (!this._isEdgeScrolling) { this._isEdgeScrolling = true; this._edgeScrollDuration = 0; } this._edgeScrollDuration += elapsed; if (this._edgeScrollDuration > editor.options.edgeScrollDelay) { const eased = editor.options.edgeScrollEaseDuration > 0 ? EASINGS.easeInCubic( Math.min( 1, this._edgeScrollDuration / (editor.options.edgeScrollDelay + editor.options.edgeScrollEaseDuration) ) ) : 1; this.moveCameraWhenCloseToEdge({ x: edgeScrollProximityFactor.x * eased, y: edgeScrollProximityFactor.y * eased }); } } } /** * Helper function to get the scroll proximity factor for a given position. * @param position - The mouse position on the axis. * @param dimension - The component dimension on the axis. * @param isCoarse - Whether the pointer is coarse. * @param insetStart - Whether the pointer is inset at the start of the axis. * @param insetEnd - Whether the pointer is inset at the end of the axis. * @internal */ getEdgeProximityFactors(position, dimension, isCoarse, insetStart, insetEnd) { const { editor } = this; const dist = editor.options.edgeScrollDistance; const pw = isCoarse ? editor.options.coarsePointerWidth : 0; const pMin = position - pw; const pMax = position + pw; const min = insetStart ? 0 : dist; const max = insetEnd ? dimension : dimension - dist; if (pMin < min) { return Math.min(1, (min - pMin) / dist); } else if (pMax > max) { return -Math.min(1, (pMax - max) / dist); } return 0; } getEdgeScroll() { const { editor } = this; const { inputs: { currentScreenPoint: { x, y } } } = editor; const screenBounds = editor.getViewportScreenBounds(); const { isCoarsePointer, insets: [t, r, b, l] } = editor.getInstanceState(); const proximityFactorX = this.getEdgeProximityFactors(x, screenBounds.w, isCoarsePointer, l, r); const proximityFactorY = this.getEdgeProximityFactors(y, screenBounds.h, isCoarsePointer, t, b); return { x: proximityFactorX, y: proximityFactorY }; } /** * Moves the camera when the mouse is close to the edge of the screen. * @public */ moveCameraWhenCloseToEdge(proximityFactor) { const { editor } = this; if (!editor.inputs.isDragging || editor.inputs.isPanning || editor.getCameraOptions().isLocked) return; if (proximityFactor.x === 0 && proximityFactor.y === 0) return; const screenBounds = editor.getViewportScreenBounds(); const screenSizeFactorX = screenBounds.w < 1e3 ? 0.612 : 1; const screenSizeFactorY = screenBounds.h < 1e3 ? 0.612 : 1; const zoomLevel = editor.getZoomLevel(); const pxSpeed = editor.user.getEdgeScrollSpeed() * editor.options.edgeScrollSpeed; const scrollDeltaX = pxSpeed * proximityFactor.x * screenSizeFactorX / zoomLevel; const scrollDeltaY = pxSpeed * proximityFactor.y * screenSizeFactorY / zoomLevel; const { x, y, z } = editor.getCamera(); editor.setCamera(new Vec(x + scrollDeltaX, y + scrollDeltaY, z)); } } export { EdgeScrollManager }; //# sourceMappingURL=EdgeScrollManager.mjs.map