UNPKG

@learn-hunger/visual-gestures

Version:

VisualGestures.js is a package that empowers users to effortlessly control the cursor, including actions such as hover, click, drag, and drop, through precise finger movements in the air.

202 lines (201 loc) 12.3 kB
import { IGestureCustomProps } from "../utilities/vg-types"; import { INormalizedLandmark } from "../utilities/vg-types-handlandmarks"; import { VgHandLandmarksDTO } from "./DTO/vg-handlandmark"; import { AVgPointerEvents } from "./abstracts/vg-pointer-events"; /** * Central Class to store states of the hand landmarks * handles triggering events * Core logic for hand gestures is maintained here */ export declare class VgPointer extends AVgPointerEvents { distance2D: number; distance3D: number; relativeDist2D: number; mouseInit: MouseEventInit; props: IGestureCustomProps; structuredLandmarks: VgHandLandmarksDTO; mouseDown: boolean; upElement: HTMLElement; palmHeight?: number; fingerHeight?: number; fingerKinkRatio: number; /*** * stateID: Flagging variable indicates the current event being performed * If stateID==0 then move event * else if stateID==1 then down event * else if stateID==2 then up event * else if stateID==3 then drag event * else if stateID==4 them drag+up= drop event */ stateID?: number; decaWindowPointer?: number; /** * decaWindow: Window contains history 'fingerKinkRatio' * initialized with array of null values * length is set to five to achieve optimal results */ decaWindow: [ number | null, number | null, number | null, number | null, number | null ]; /** * tipWindow: Window contains history 'INormalizedLandmark' of TIP of INDEX finger * initialized with array of null values * length is set to five to achieve optimal results */ tipWindow: [ INormalizedLandmark | null, INormalizedLandmark | null, INormalizedLandmark | null, INormalizedLandmark | null, INormalizedLandmark | null ]; /** * motionWindow: Window contains 'INormalizedLandmark' of MCP of INDEX finger * initialized with array of null values * 0th index contains the significant past 'INormalizedLandmark' * 1th index contains the current 'INormalizedLandmark' */ motionWindow: [INormalizedLandmark | null, INormalizedLandmark | null]; constructor(); set setElement(element: Element); private get getProps(); updateProps(mouseProp: MouseEventInit, customProps: IGestureCustomProps): void; trigger(): void; private kinkLogic; /** * Signature : pseudoDown() * Description : Used to check whether the mouse(cursor) is in 'down' state at current instance of time * _____________________________________________________________________________________ * ALGORITHM * _____________________________________________________________________________________ * If 'structuredLandmarks' are correctly detected, 'fingerKinkRatio' is calculated, and current 'stateID == 0' (onmousemove event) * * If 'decaWindow[0]' (fingerKinkRatio of previous frame) is calculated and significant decrement (magnitude= 200) in 'fingerKinkRatio' is observed * * * Store current 'fingerKinkRatio' at 'decaWindow[1]' [ decaWindow[0], decaWindow[1] attains hibernation ] * * * Nullify decaWindow after 1th-index [ decaWIndow[2], decaWindow[3], decaWindow[4] are set to implement sliding window ] * * * Store current TIP of INDEX finger at 'tipWindow[1]' [ tipWindow[0], tipWindow[1] attains hibernation ] * * * Nullify tipWindow after 1th-index [ tipWindow[2], tipWindow[3], tipWindow[4] are set to implement sliding window ] * * * Set the 'decaWindowPointer' to '1' indicating the index where 'onmousedown' event is triggered * * * Set stateID to '1' representing 'onmousedown' operation is triggered * * * Set 'motionWindow[0]' with INormalizedLandmark of INDEX.MCP at instance where down operation is triggered * * * Call 'triggerMouseDown' event at 'tipWindow[0]' which contains INormalizedLandmark which corresponds to the starting(initial) coordinates from where 'onmousedown' event is started * * * Nullify 'motionWindow[0]' to hold the successive INormalizedLandmarks of INDEX.MCP * * * 'true' is returned indicating mouse is down at the current instance of time * * Else * * * If 'decaWindow' is not completely filled * * * * Increment decaWindowPointer by 1 * * * * Append current 'fingerKinkRatio' to 'decaWindow' * * * * Append current INDEX.TIP to 'tipWindow' * * * Else * * * * Shift-left all values of 'decaWindow' to immediate preceeding index [ Sliding Operation ] * * * * Update 'decaWindow[4]' with current 'fingerKinkRatio' * * * * Shift-left all values of 'tipWindow' to immediate preceeding index [ Sliding Operation ] * * * * Update 'tipWindow[4]' with current INDEX.TIP * * * Set 'motionWindow[0]' with current 'INormalizedLandmark' of INDEX.MCP * * * Nullify 'motionWindow[1]' as current event being performed is 'onmousedown' * * * 'false' is returned indicating mouse is not down at the current instance of time * Else * * 'false' is returned indicating mouse is not down at the current instance of time */ private pseudoDown; /** * Signature : pseudoUp() * Description : Used to check whether the mouse(cursor) is in 'up' state at current instance of time * _____________________________________________________________________________________ * ALGORITHM * _____________________________________________________________________________________ * If current state of cusor is 'onmousedown'(stateID == 1) or 'onmousedrag'(stateID == 3) * * Update the motionWindow[1] with current INDEX.MCP to track movement of hand from initial position (position at which 'pseudoDown()' is triggered) * * If significant increment (>=200) in 'fingerKinkRatio' is observed * * * If previous operation is 'drag'(stateID=3) * * * * Set 'stateID = 4' representing 'onmousedrop' event * * * Else (if previous operation is 'down'[stateID=1]) * * * * Set 'stateID = 2' representing 'onmouseup' event * * Else * * * If 'decaWindow' is completely filled using 'decaWindowPointer' * * * * Increment 'decaWindowPointer' by 1 * * * * Append current 'fingerKinkRatio' to 'decaWindow' * * * * Append current INDEX.TIP to 'tipWindow' * * * * Update the motionWindow[1] with current INDEX.MCP to track movement of hand from initial position (position at which 'pseudoDown()' is triggered) * * * Else if 'decaWindow' is completely filled * * * * Take copy of values of 'decaWindow' into variables * * * * Update the 'decaWindow' shifting one-index left * * * * Update 'decaWindow[4]' with current 'fingerKinkRatio' * * * * Take copy of values of 'tipWindow' into variables * * * * Update the 'tipWindow' shifting one-index left * * * * Update 'tipWindow[4]' with current INDEX.TIP * * * If current event is 'onmousedrag' ('stateID == 3') * * * * Call 'triggerMouseMove' event (corresponds to onmousemove in traditional mouse-based controls) * 'false' is returned indicating mouse is not up at the current instance of time */ private pseudoUp; /** * Signature : pseudoClick() * Description : Used to check whether the mouse(cursor) is in 'click' state at current instance of time * _____________________________________________________________________________________ * ALGORITHM * _____________________________________________________________________________________ * If ( (current state of cursor is 'onmouseup' ('stateID == 2') and significant hand movement is not observed) or * (current state of cursor is 'onmousedrop' ('stateID == 4') and significant hand movement is not observed) ) * * Call 'triggerMouseUp' event (corresponds to 'onmouseup' in traditional mouse-based controls) * * Call 'triggerMouseClick' event (corresponds to 'onmouseclick' in traditional mouse-based controls) * * Update 'decaWindow[0]' with current 'fingerKinkRatio' at the instance where 'pseudoClick()' ('onmouseclick') operation is triggered * * Nullify entire 'decaWindow' after 0th- index * * Update 'tipWindow[0]' with current INDEX.TIP at the instance where 'pseudoClick()' ('onmouseclick') operation is triggered * * Nullify entire 'tipWindow' after 0th-index * * Set 'decaWindowPointer' pointing to '0'th-index * * Update 'motionWindow[0]' with 'INormalizedLandmark' of current INDEX.MCP * * Nullify 'motionWindow[1]' to hold the successive 'INormalizedLandmarks' of INDEX.MCP * * Update stateID to '0' denoting 'onmousemove' as the current event as 'pseudoClick()' ('onmouseclick') operation is completed * * 'true' is returned indicating mouse is clicked at the current instance of time * 'false' is returned indicating mouse is not clicked at the current instance of time */ private pseudoClick; /** * Signature : pseudoDrag() * Description : Used to check whether the mouse(cursor) is in 'drag' state at current instance of time * _____________________________________________________________________________________ * ALGORITHM * _____________________________________________________________________________________ * If ( current event is 'pseudoDown()' ('stateID == 1') and * significant hand movement is observed ('weightedEuclideanDistance' between 'motionWindow[0]' and 'motionWindow[1]' is greater than '0.08') ) * * Set 'stateID' to '3' indicating 'onmousedrag' ('pseudoDrag') operation is triggered at the current instance of time * * 'true' is returned indicating mouse is dragged at the current instance of time * 'false' is returned indicating mouse is not dragged at the current instance of time */ private pseudoDrag; /** * Signature : pseudoDrop() * Description : Used to check whether the mouse(cursor) is in 'drop' state at current instance of time * _____________________________________________________________________________________ * ALGORITHM * _____________________________________________________________________________________ * If * ( current event is 'pseudoDrop()' ('stateID == 4') and significant hand movement is observed ('weightedEuclideanDistance' between 'motionWindow[0]' and 'motionWindow[1]' is greater than '0.08') ) or * ( current event is 'pseudoUp()' ('stateID == 2') and significant hand movement is observed ('weightedEuclideanDistance' between 'motionWindow[0]' and 'motionWindow[1]' is greater than '0.08') ) * * Call 'triggerMouseDrop' event (corresponds to 'onmousedrop' in traditional mouse-based controls) * * Update 'decaWindow[0]' with current 'fingerKinkRatio' at the instance where 'pseudoDrop()' operation is triggered * * Nullify entire 'decaWindow' after 0th- index * * Update 'tipWindow[0]' with INDEX.TIP at the instance where 'pseudoDrop()' operation is triggered * * Nullify entire 'tipWindow' after 0th- index * * Set 'decaWindowPointer' to '0' indicating current state is 'onmousemove' as 'onmousedrop' ('pseudoDrop()') event has completed at the current instance of time * * Set 'motionWindow[0]' with current 'INormalizedLandmark' of INDEX.MCP * * Nullify 'motionWindow[1]' as current event being performed is 'onmousedrop' and to hold the successive 'INormalizedLandmarks' of INDEX.MCP * * Set 'stateID' to '0' representing 'onmousemove' operation is triggered as 'onmousedrop' event is completed at the current instance of time * * 'true' is returned indicating mouse is dropped at the current instance of time * 'false' is returned indicating mouse is not dropped at the current instance of time */ private pseudoDrop; private staticEventsInitialiser; /** * Reset all sliding windows (decaWindow, tipWindow, motionWindow), * pointer (decaWindowPointer), and * flag (stateID) * if hand landmarks are not detected */ resetStatesOnNoLandmarks(): void; private getElement; }