UNPKG

@lhs7/wheel-selector

Version:
125 lines (124 loc) 4.69 kB
import { WheelSelector } from "./WheelSelector"; import { disableIframePointerEvents, hideMouseCursor, restoreIframePointerEvents, showMouseCursor, } from "../util/events"; export class MouseWheelSelector extends WheelSelector { constructor(options) { super(options); this.isLeftClicked = false; this.activateKey = null; this.startPos = null; this.lineInfo = null; this.eventHandlers = { keydown: (event) => { if (event.key === this.activateKey) { const centerX = window.innerWidth / 2; const centerY = window.innerHeight / 2; hideMouseCursor(document); this.activateSelector({ x: centerX, y: centerY }); } }, keyup: (event) => { if (event.key === this.activateKey) { showMouseCursor(document); this.deactivateSelector(); } }, click: (event) => { if (this.isActive) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); //클릭이벤트 중복 처리를 막기위해 더 뒤에서 처리되는 click에서 처리 this.deactivateSelector(); } }, mousedown: (event) => { if (event.button === 0) this.isLeftClicked = true; if (event.button === 2 && this.isLeftClicked) { event.preventDefault(); this.activateSelector({ x: event.clientX, y: event.clientY }); } }, mousemove: (event) => { if (!this.isActive) { this.startPos = { x: event.clientX, y: event.clientY }; return; } if (this.position === null) return null; const { angle, length } = this.calculLine(event.clientX, event.clientY); this.selectedItemNo = this.checkSelected({ angle, length }); this.lineInfo = { angle, length }; this.redraw(); }, mouseup: (event) => { if (this.isActive) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); if (event.button === 2) this.deactivateSelector(); } if (event.button === 0) { this.isLeftClicked = false; } }, contextmenu: (event) => { if (this.isLeftClicked === true) event.preventDefault(); }, }; if (options) this.activateKey = options.activateKey ? options.activateKey : null; this.addEventHandlers(); } activateSelector({ x, y }) { disableIframePointerEvents(document); super.activateSelector({ x, y }); } calculLine(ex, ey) { const { x, y } = this.startPos; const [dx, dy] = [ex - x, ey - y]; const angle = Math.atan2(dy, dx); const length = Math.sqrt(dy * dy + dx * dx); return { angle, length, }; } checkSelected({ angle, length, }) { if (length < this.innerDistance) return "CANCEL"; const normalizedAngle = ((angle % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI); let startAngle = 0; const angleStep = (2 * Math.PI) / this.items.length; for (let idx = 0; idx < this.items.length; idx++) { const endAngle = startAngle + angleStep; if (normalizedAngle >= startAngle && normalizedAngle < endAngle) { return idx; } startAngle = endAngle; } return null; } deactivateSelector() { restoreIframePointerEvents(document); this.lineInfo = null; super.deactivateSelector(); this.triggerSelected(); } addEventHandlers() { if (document === null) return; for (const [event, handler] of Object.entries(this.eventHandlers)) { document.addEventListener(event, handler, true); } } removeEventHandlers() { if (document === null) return; for (const [event, handler] of Object.entries(this.eventHandlers)) { document.removeEventListener(event, handler, true); } } }