@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
133 lines (116 loc) • 4.59 kB
text/typescript
/* eslint-disable @typescript-eslint/no-use-before-define */
/**
* Measure vertical or horizontal intersection of current and target object
* depending on given direction.
* @param {Object} current rect object {right, left, top, bottom, x, y, width. height}
* @param {Object} target rect object {right, left, top, bottom, x, y, width. height}
* @param {Object} direction of measuring intersection
* @returns {Int} Returns vaertival intersection of current and target object
*/
export function measureDimensionalIntersection(direction, current, target) {
if (direction.isHorizontal) {
return measureVerticalIntersectiont(current, target);
} else {
return measureHorizontalIntersection(current, target);
}
}
/**
* Measure vertical intersection of current and target object
* ┏━━━━┓
* ┃ ┃┄┄┄┄┏━━━━┓┄┄ ← Vertical intersection of 2 elements
* ┗━━━━┛┄┄┄┄┃ ┃┄┄ ← for horizontal movement
* ┗━━━━┛
* @param {Object} current rect object {right, left, top, bottom, x, y, width. height}
* @param {Object} target rect object {right, left, top, bottom, x, y, width. height}
* @returns {Int} Returns vertical intersection of current and target object
*/
export function measureVerticalIntersectiont(current, target) {
if (target.top >= current.bottom || target.bottom <= current.top) {
return 0;
}
const top = Math.max(current.top, target.top);
const bottom = Math.min(current.bottom, target.bottom);
return bottom - top;
}
/**
* Measure horizontal intersection of current and target object
* ┏━━━━┓
* ┃ ┃
* ┗━━━━┛
* ┆ ┆
* ┏━━━━┓
* ┃ ┃
* ┗━━━━┛
* ↑ ↑
* Horizontal intersection of 2 elements for vertical movement
* @param {Object} current rect object {right, left, top, bottom, x, y, width. height}
* @param {Object} target rect object {right, left, top, bottom, x, y, width. height}
* @returns {Int} Returns horizontal intersection of current and target object
*/
export function measureHorizontalIntersection(current, target) {
if (target.right <= current.left || target.left >= current.right) {
return 0;
}
const left = Math.max(current.left, target.left);
const right = Math.min(current.right, target.right);
return right - left;
}
/**
* Returns always positive value to the elements in specific direction
* For instance if I direction is left and target is on the left it will return a
* distance to current direction which will be > 0. If target is on the right of the
* current element then returned value will be negative
* @param {Object} current rect object {right, left, top, bottom, x, y, width. height}
* @param {Object} target rect object {right, left, top, bottom, x, y, width. height}
* @param {Object} direction direction of the navigation intent any of ["right", "left", "up", "down"]
* @returns {Int} distance to target object in soecified direction
*/
export function measureDistance(direction, current, target) {
switch (direction.value) {
case "right":
return -1 * (current.right - target.left);
case "left":
return current.left - target.right;
case "up":
if (target.x + target.width < 0) {
// Offscreen to the left, make sure it's too far away ( more than -1 away)
return -10000;
}
return current.top - target.bottom;
case "down":
if (target.x > 1920) {
// // Offscreen to the right, make sure it's too far away ( more than -1 away)
return -10000;
}
return -1 * (current.bottom - target.top);
}
}
export function measureEuclidianDistanceToCenter(current, target) {
const currentCenter = getCenter(current);
const targetCenter = getCenter(target);
return Math.sqrt(
Math.pow(targetCenter.x - currentCenter.x, 2) +
Math.pow(targetCenter.y - currentCenter.y, 2)
);
}
function getCenter(rect) {
const { left, right, top, bottom } = rect;
return {
x: (left + right) / 2,
y: (top + bottom) / 2,
};
}
export function isOnDirection(direction, current, target) {
const currentCenter = getCenter(current);
const targetCenter = getCenter(target);
if (direction.isHorizontal) {
return direction.value === "right"
? targetCenter.x - currentCenter.x > 0
: targetCenter.x - currentCenter.x < 0;
}
if (direction.isVertical) {
return direction.value === "up"
? targetCenter.y - currentCenter.y < 0
: targetCenter.y - currentCenter.y > 0;
}
}