-
Notifications
You must be signed in to change notification settings - Fork 0
/
mouse.js
84 lines (63 loc) · 1.95 KB
/
mouse.js
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
import {
predictionFactor,
predictiveTimeout
} from './constants';
import {
addHoverClass,
removeHoverClass
} from './styles';
//17 last positions = 16 last differences
const positionsFull = mousePositions => mousePositions.length === 17;
const isIn = (x,y,coordinates) =>
x > coordinates.x &&
x < (coordinates.x + coordinates.width) &&
y > coordinates.y &&
y < (coordinates.y + coordinates.height);
export const getMouseHandler = (filter, elements, predict) => {
const coordinatesCheckers = [];
for(let i = 0, l = elements.length; i < l; i++){
const element = elements[i],
rect = element.getBoundingClientRect();
coordinatesCheckers.push((x,y) => isIn(x,y,rect));
}
const timeoutIds = new Array(elements.length);
let globalX,
globalY,
mousePositions = [];
return e => {
let x, y;
if (document.all) {
x = event.x + document.body.scrollLeft;
y = event.y + document.body.scrollTop;
} else {
x = e.pageX;
y = e.pageY;
}
globalX = globalX || x;
globalY = globalY || y;
filter.update([(x - globalX)*predictionFactor, (y - globalY)*predictionFactor]);
const filterState = filter.state(),
predictX = globalX + filterState[0],
predictY = globalY + filterState[1];
if(!predict || !positionsFull(mousePositions) || predict(mousePositions)){
for(let i = 0, l = coordinatesCheckers.length; i < l; i++){
if(coordinatesCheckers[i](predictX, predictY)){
const element = elements[i];
if(!timeoutIds[i]){
addHoverClass(element);
timeoutIds[i] = setTimeout(() => {
removeHoverClass(element);
delete timeoutIds[i];
}, predictiveTimeout);
}
}
}
}
globalX = x;
globalY = y;
if(predict){
positionsFull(mousePositions) && mousePositions.shift();
mousePositions.push([x,y]);
}
}
}