UNPKG

@paperbits/common

Version:
78 lines (67 loc) 3.27 kB
import { BehaviorHandle } from "./behavior"; import { Events } from "../events"; export interface AngleBehaviorOptions { /** * Callback function invoked when the angle changes. * @param angle The new angle in degrees (0-359). */ onChange: (angle: number) => void; } export class AngleBehavior { public static attach(element: HTMLElement, options: AngleBehaviorOptions): BehaviorHandle { const rect = element.getBoundingClientRect(); const centerX = Math.floor(rect.width / 2); const centerY = Math.floor(rect.height / 2); let tracking = false; const determineAngle = (x: number, y: number) => { const dx = centerX - x; const dy = centerY - y; let theta = Math.atan2(dy, dx) * 180 / Math.PI; theta += -90; // Adjusting to make 0 degrees at the top if (theta < 0) { theta += 360; } options.onChange(Math.floor(theta)); }; const onMouseDown = (event: MouseEvent) => { tracking = true; determineAngle(event.offsetX, event.offsetY); }; const onMouseUp = (event: MouseEvent) => { if (tracking) { // Only determine angle if tracking was active determineAngle(event.offsetX, event.offsetY); } tracking = false; }; const onMouseMove = (event: MouseEvent) => { if (!tracking) { return; } determineAngle(event.offsetX, event.offsetY); }; const onMouseLeave = (event: MouseEvent) => { // Optional: if you want tracking to stop if mouse leaves the element // if (tracking) { // determineAngle(event.offsetX, event.offsetY); // Update one last time // } // tracking = false; }; element.addEventListener(Events.MouseDown, onMouseDown); // Listen to mouseup and mousemove on the document or a specific capturing parent // to handle cases where the mouse is released outside the element. // However, the original code listened on the element itself for mouseup and mousemove with capture=true. // For now, sticking to element listeners as per original, but document-level listeners are often more robust for dragging. document.addEventListener(Events.MouseUp, onMouseUp, true); // Changed to document to ensure mouseup is caught document.addEventListener(Events.MouseMove, onMouseMove, true); // Changed to document for better tracking experience // element.addEventListener(Events.MouseLeave, onMouseLeave); // Optional: see comment above return { detach: () => { element.removeEventListener(Events.MouseDown, onMouseDown); document.removeEventListener(Events.MouseUp, onMouseUp, true); document.removeEventListener(Events.MouseMove, onMouseMove, true); // element.removeEventListener(Events.MouseLeave, onMouseLeave); tracking = false; // Ensure tracking is reset } }; } }