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.

158 lines 6.49 kB
import { DefaultConfig } from "./app/config/defalut-config"; import { AVgCommon } from "./app/shared/vg-cursor-pointer-abstract"; import { VgPointer } from "./app/pointer/custom-events"; import { VgHandLandmarksDTO } from "./app/pointer/DTO/vg-handlandmark"; /** * Central Class to Hold all kinds of gestures such as hand for now and * may be audio gestures for future */ export class VisualGestures extends AVgCommon { constructor(container = DefaultConfig.instance.cursorContainer, pointer = DefaultConfig.instance.pointer) { super(container); //initialise the central hand gesture class this.mouseEvents = new VgPointer(); //initialise the constant properties of the cursor etc this.props = { pointer: { keypoint: pointer, currentLandmark: DefaultConfig.instance.cursorPosition, }, cursorElement: this.cursor, cursorSpeed: 1, }; this.props.element = {}; } /** * here common properties gets updated whenever landmarks gets detected * on each frame * @private * @type {{}} */ set setLandmarks(landmarks) { if (landmarks.length > 0) { this.props.previousLandmarks = this.props.currentLandmarks; this.props.currentLandmarks = landmarks; this.props.previousStructuredLandmarks = this.props.structuredLandmarks; this.props.structuredLandmarks = new VgHandLandmarksDTO(landmarks); this.props.pointer.previousLandmark = this.props.pointer.currentLandmark; this.props.pointer.currentLandmark = landmarks[this.props.pointer.keypoint]; //update delta landmarks of pointer this.props.pointer.deltaLandmark = (() => { const prev = this.props.pointer.previousLandmark ? this.props.pointer.previousLandmark : { x: 0, y: 0, z: 0 }; const { x, y, z } = this.props.pointer.currentLandmark; const deltaLandmarks = { x: x - prev.x, y: y - prev.y, z: z - prev.z, }; return deltaLandmarks; })(); //update delta landmarks of all landmarks this.props.deltaLandmarks = this.props.currentLandmarks.map((i, index) => { const prev = this.props.previousLandmarks ? this.props.previousLandmarks[index] : { x: 0, y: 0, z: 0 }; const { x, y, z } = i; const deltaLandmarks = { x: x - prev.x, y: y - prev.y, z: z - prev.z, }; return deltaLandmarks; }); } } /** * Calculates and normalizes the position of the cursor position * to fit within the viewport of the container element * called only when landmarks got detected * @private * @readonly * @type {MouseEventInit} */ get mouseInit() { let { x: pointerX, y: pointerY } = this.props.pointer.currentLandmark; const { clientWidth: cursorX, clientHeight: cursorY } = this.sizes.cursor; const { clientWidth: containerX, clientHeight: containerY } = this.sizes.container; //normalise x ,y to 0-1 //here x is 1 to 0 from left to right wrt screen const speed = this.props.cursorSpeed; // const temp=pointerX pointerX = pointerX * speed > 1 ? 1 : pointerX * speed; pointerX = pointerX * speed < 0 ? 0 : pointerX * speed; pointerY = pointerY * speed < 0 ? 0 : pointerY * speed; pointerY = pointerY * speed > 1 ? 1 : pointerY * speed; //TODO Z axis //screen wise normalisation to fit into view port lower boundaries //right operator here is to make the cursor inside the viewport of upper boundaries const clientX = Math.min(Math.max((1 - pointerX) * containerX, 0), containerX - cursorX); const clientY = Math.min(Math.max(pointerY * containerY, 0), containerY - cursorY); const m = { clientX: clientX, clientY: clientY, }; return m; } /** * It assigns the timestamp of the current frame and previous frame * which will be used in core logic of the gestures in vgPointer class * @private * @type {number} */ set setTimer(timeStamp) { if (!this.props.time) { //setting the initial timestamps ie timer at first frame this.props.time = { deltaTime: timeStamp, timeStamp: timeStamp, }; return; } //timestamps after first frame this.props.time.deltaTime = timeStamp - this.props.time.timeStamp; this.props.time.timeStamp = timeStamp; } /** * This is the handler which gets called by the end developer * based on the handlandmarks detected setLandmarks and mouseInit gets called * Timer gets called every time to update the timestamp irrespective of handlandmarks detected or not * @param landmark * @param timeStamp * @param cursorSpeed */ detect(landmark, timeStamp, cursorSpeed = 1) { this.setTimer = timeStamp; if (landmark) { //update landmarks and cursor position and delta landmarks as per detected landmarks this.setLandmarks = landmark; /** * callibrate with cursor sizes in the first frame * call actual detection only after the first frame * in first frame no events get fired */ const isCallibrated = this.props.sizes; if (isCallibrated) { try { this.props.cursorSpeed = cursorSpeed; this.mouseEvents.updateProps(this.mouseInit, this.props); } catch (err) { console.log(err); } } else { //first frame callibration this.initialiseSizes(); this.props.sizes = this.sizes; } } else { //whenever landmarks are not detected , reset the states in vgPointer class this.mouseEvents.resetStatesOnNoLandmarks(); } } } //# sourceMappingURL=index.js.map