src/core/util.js
/**
* @file util.js
* Various accessor and mutator functions to handle state and validation.
*/
const CIRCLE_DEGREES = 360;
const HALF_CIRCLE_DEGREES = 180;
/**
* Contains generic helper functions
* @type {Object}
* @namespace util
*/
var util = {
/**
* Normalizes window events to be either of type start, move, or end.
* @param {String} type - The event type emitted by the browser
* @returns {null|String} - The normalized event, or null if it is an event not predetermined.
*/
normalizeEvent(type) {
switch (type) {
case 'mousedown' :
case 'touchstart' :
case 'pointerdown' :
return 'start';
case 'mousemove' :
case 'touchmove' :
case 'pointermove' :
return 'move';
case 'mouseup' :
case 'touchend' :
case 'pointerup' :
return 'end';
default :
return null;
}
},
/*normalizeEvent*/
/**
* Determines if the current and previous coordinates are within or up to a certain tolerance.
* @param {Number} currentX - Current event's x coordinate
* @param {Number} currentY - Current event's y coordinate
* @param {Number} previousX - Previous event's x coordinate
* @param {Number} previousY - Previous event's y coordinate
* @param {Number} tolerance - The tolerance in pixel value.
* @returns {boolean} - true if the current coordinates are within the tolerance, false otherwise
*/
isWithin(currentX, currentY, previousX, previousY, tolerance) {
return ((Math.abs(currentY - previousY) <= tolerance) &&
(Math.abs(currentX - previousX) <= tolerance));
},
/*isWithin*/
/**
* Calculates the distance between two points.
* @param x0
* @param x1
* @param y0
* @param y1
* @returns {number} The numerical value between two points
*/
distanceBetweenTwoPoints(x0, x1, y0, y1) {
var dist = (Math.sqrt(((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0))));
return Math.round(dist * 100) / 100;
},
/**
* Calculates the midpoint coordinates between two points.
* @param x0
* @param x1
* @param y0
* @param y1
* @returns {Object} The coordinates of the midpoint.
*/
getMidpoint(x0, x1, y0, y1) {
return {
x: ((x0 + x1) / 2),
y: ((y0 + y1) / 2)
};
},
/**
* Calculates the angle between the projection and an origin point.
* | (projectionX,projectionY)
* | /°
* | /
* | /
* | / θ
* | /__________
* ° (originX, originY)
* @param {number} originX
* @param {number} originY
* @param {number} projectionX
* @param {number} projectionY
* @returns {number} - Degree along the unit circle where the project lies
*/
getAngle(originX, originY, projectionX, projectionY) {
var angle = Math.atan2(projectionY - originY, projectionX - originX) *
((HALF_CIRCLE_DEGREES) / Math.PI);
return CIRCLE_DEGREES - ((angle < 0) ? (CIRCLE_DEGREES + angle) : angle);
},
/**
* Calculates the angular distance in degrees between two angles along the unit circle
* @param {number} start - The starting point in degrees
* @param {number} end - The ending point in degrees
* @returns {number} The number of degrees between the starting point ant ending point. Negative
* degrees denote a clockwise direction, and positive a counter-clockwise direction.
*/
getAngularDistance(start, end) {
var angle = (end - start) % CIRCLE_DEGREES;
var sign = (angle < 0) ? 1 : -1;
angle = Math.abs(angle);
return (angle > HALF_CIRCLE_DEGREES) ? sign * (CIRCLE_DEGREES - angle) : sign * angle;
},
/**
* Calculates the velocity of pixel/milliseconds between two points
* @param {Number} startX
* @param {Number} startY
* @param {Number} startTime
* @param {Number} endX
* @param {Number} endY
* @param {Number} endTime
* @returns {Number} velocity of px/time
*/
getVelocity(startX, startY, startTime, endX, endY, endTime) {
var distance = this.distanceBetweenTwoPoints(startX, endX, startY, endY);
return (distance / (endTime - startTime));
},
/**
* Returns the farthest right input
* @param inputs
*/
getRightMostInput(inputs) {
var rightMost = null;
var distance = Number.MIN_VALUE;
inputs.forEach(input => {
if (input.initial.x > distance) {
rightMost = input;
}
});
return rightMost;
},
/**
* Determines is the value is an integer and not a floating point
* @param value
* @returns {boolean}
*/
isInteger(value) {
return (typeof value === 'number') && (value % 1 === 0);
},
/**
* Determines if the x,y position of the input is within then target.
* @param x -clientX
* @param y -clientY
* @param target
*/
isInside(x, y, target) {
var rect = target.getBoundingClientRect();
return ((x > rect.left && x < rect.left + rect.width) && (y > rect.top && y < rect.top + rect.height));
},
/**
* Polyfill for event.propagationPath
* @param event
*/
getPropagationPath(event) {
if (event.path) {
return event.path;
} else {
var path = [];
var node = event.target;
while (node != document) {
path.push(node);
node = node.parentNode;
}
return path;
}
},
/**
* Retrieve the index inside the path array
* @param path
* @param element
* @returns {element}
*/
getPathIndex(path, element) {
var index = path.length;
path.forEach(obj => {
if (obj === element) {
index = i;
}
});
return index;
},
setMSPreventDefault(element) {
element.style['-ms-content-zooming'] = 'none';
element.style['touch-action'] = 'none';
},
removeMSPreventDefault(element) {
element.style['-ms-content-zooming'] = '';
element.style['touch-action'] = '';
}
};
export default util;