-
Notifications
You must be signed in to change notification settings - Fork 920
/
hitTest.js
executable file
·115 lines (100 loc) · 2.41 KB
/
hitTest.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
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
'use strict';
var FrameUtils = require('./FrameUtils');
var EventTypes = require('./EventTypes');
/**
* RenderLayer hit testing
*
* @param {Event} e
* @param {RenderLayer} rootLayer
* @param {?HTMLElement} rootNode
* @return {RenderLayer}
*/
function hitTest (e, rootLayer, rootNode) {
var touch = e.touches ? e.touches[0] : e;
var touchX = touch.pageX;
var touchY = touch.pageY;
var rootNodeBox;
if (rootNode) {
rootNodeBox = rootNode.getBoundingClientRect();
touchX -= rootNodeBox.left;
touchY -= rootNodeBox.top;
}
touchY = touchY - window.pageYOffset;
touchX = touchX - window.pageXOffset;
return getLayerAtPoint(
rootLayer,
e.type,
FrameUtils.make(touchX, touchY, 1, 1),
rootLayer.translateX || 0,
rootLayer.translateY || 0
);
}
/**
* @private
*/
function sortByZIndexDescending (layer, otherLayer) {
return (otherLayer.zIndex || 0) - (layer.zIndex || 0);
}
/**
* @private
*/
function getHitHandle (type) {
var hitHandle;
for (var tryHandle in EventTypes) {
if (EventTypes[tryHandle] === type) {
hitHandle = tryHandle;
break;
}
}
return hitHandle;
}
/**
* @private
*/
function getLayerAtPoint (root, type, point, tx, ty) {
var layer = null;
var hitHandle = getHitHandle(type);
var sortedChildren;
var hitFrame = FrameUtils.clone(root.frame);
// Early bail for non-visible layers
if (typeof root.alpha === 'number' && root.alpha < 0.01) {
return null;
}
// Child-first search
if (root.children) {
sortedChildren = root.children.slice().reverse().sort(sortByZIndexDescending);
for (var i=0, len=sortedChildren.length; i < len; i++) {
layer = getLayerAtPoint(
sortedChildren[i],
type,
point,
tx + (root.translateX || 0),
ty + (root.translateY || 0)
);
if (layer) {
break;
}
}
}
// Check for hit outsets
if (root.hitOutsets) {
hitFrame = FrameUtils.inset(FrameUtils.clone(hitFrame),
-root.hitOutsets[0], -root.hitOutsets[1],
-root.hitOutsets[2], -root.hitOutsets[3]
);
}
// Check for x/y translation
if (tx) {
hitFrame.x += tx;
}
if (ty) {
hitFrame.y += ty;
}
// No child layer at the given point. Try the parent layer.
if (!layer && root[hitHandle] && FrameUtils.intersects(hitFrame, point)) {
layer = root;
}
return layer;
}
module.exports = hitTest;
module.exports.getHitHandle = getHitHandle;