forked from react-native-elements/react-native-elements
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetTooltipCoordinate.js
More file actions
139 lines (119 loc) · 3.92 KB
/
Copy pathgetTooltipCoordinate.js
File metadata and controls
139 lines (119 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
const getArea = (a, b) => a * b;
const getPointDistance = (a, b) =>
Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
export const getElementVisibleWidth = (elementWidth, xOffset, ScreenWidth) => {
// Element is fully visible OR scrolled right
if (xOffset >= 0) {
return xOffset + elementWidth <= ScreenWidth // is element fully visible?
? elementWidth // element is fully visible;
: ScreenWidth - xOffset; // calculate visible width of scrolled element
}
// Element is scrolled LEFT
return elementWidth - xOffset; // calculate visible width of scrolled element
};
/*
type Coord = {
x: number,
y: number,
};
~Tooltip coordinate system:~
The tooltip coordinates are based on the element which it is wrapping.
We take the x and y coordinates of the element and find the best position
to place the tooltip. To find the best position we look for the side with the
most space. In order to find the side with the most space we divide the the
surroundings in four quadrants and check for the one with biggest area.
Once we know the quandrant with the biggest area it place the tooltip in that
direction.
To find the areas we first get 5 coordinate points. The center and the other 4 extreme points
which together make a perfect cross shape.
Once we know the coordinates we can get the length of the vertices which form each quadrant.
Since they are squares we only need two.
*/
const getTooltipCoordinate = (
x,
y,
width,
height,
ScreenWidth,
ScreenHeight,
tooltipWidth,
tooltipHeight,
withPointer
) => {
// The following are point coordinates: [x, y]
const center = [
x + getElementVisibleWidth(width, x, ScreenWidth) / 2,
y + height / 2,
];
const pOne = [center[0], 0];
const pTwo = [ScreenWidth, center[1]];
const pThree = [center[0], ScreenHeight];
const pFour = [0, center[1]];
// vertices
const vOne = getPointDistance(center, pOne);
const vTwo = getPointDistance(center, pTwo);
const vThree = getPointDistance(center, pThree);
const vFour = getPointDistance(center, pFour);
// Quadrant areas.
// type Areas = {
// area: number,
// id: number,
// };
const areas = [
getArea(vOne, vFour),
getArea(vOne, vTwo),
getArea(vTwo, vThree),
getArea(vThree, vFour),
].map((each, index) => ({ area: each, id: index }));
const sortedArea = areas.sort((a, b) => b.area - a.area);
// deslocated points
const dX = 0.001;
const dY = height / 2;
// Deslocate the coordinates in the direction of the quadrant.
const directionCorrection = [[-1, -1], [1, -1], [1, 1], [-1, 1]];
const deslocateReferencePoint = [
[-tooltipWidth, -tooltipHeight],
[0, -tooltipHeight],
[0, 0],
[-tooltipWidth, 0],
];
// current quadrant index
const qIndex = sortedArea[0].id;
const getWithPointerOffsetY = () =>
withPointer ? 10 * directionCorrection[qIndex][1] : 0;
const getWithPointerOffsetX = () =>
withPointer ? center[0] - 18 * directionCorrection[qIndex][0] : center[0];
const newX =
getWithPointerOffsetX() +
(dX * directionCorrection[qIndex][0] + deslocateReferencePoint[qIndex][0]);
return {
x: constraintX(newX, qIndex, center[0], ScreenWidth, tooltipWidth),
y:
center[1] +
(dY * directionCorrection[qIndex][1] +
deslocateReferencePoint[qIndex][1]) +
getWithPointerOffsetY(),
};
};
const constraintX = (newX, qIndex, x, ScreenWidth, tooltipWidth) => {
switch (qIndex) {
// 0 and 3 are the left side quadrants.
case 0:
case 3: {
const maxWidth = newX > ScreenWidth ? ScreenWidth - 10 : newX;
return newX < 1 ? 10 : maxWidth;
}
// 1 and 2 are the right side quadrants
case 1:
case 2: {
const leftOverSpace = ScreenWidth - newX;
return leftOverSpace >= tooltipWidth
? newX
: newX - (tooltipWidth - leftOverSpace + 10);
}
default: {
return 0;
}
}
};
export default getTooltipCoordinate;