forked from playcanvas/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtouch.js
More file actions
189 lines (162 loc) · 6.93 KB
/
touch.js
File metadata and controls
189 lines (162 loc) · 6.93 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
pc.extend(pc, function () {
/**
* @name pc.TouchEvent
* @class A Event corresponding to touchstart, touchend, touchmove or touchcancel. TouchEvent wraps the standard
* browser event and provides lists of {@link pc.Touch} objects.
* @description Create a new TouchEvent from an existing browser event
* @param {pc.TouchDevice} device The source device of the touch events
* @param {TouchEvent} event The original browser TouchEvent
* @property {Element} element The target Element that the event was fired from
* @property {pc.Touch[]} touches A list of all touches currently in contact with the device
* @property {pc.Touch[]} changedTouches A list of touches that have changed since the last event
*/
var TouchEvent = function (device, event) {
this.element = event.target;
this.event = event;
this.touches = [];
this.changedTouches = [];
if (event) {
var i, l = event.touches.length;
for (i = 0; i < l; i++) {
this.touches.push(new Touch(event.touches[i]));
}
l = event.changedTouches.length;
for (i = 0; i < l; i++) {
this.changedTouches.push(new Touch(event.changedTouches[i]));
}
}
};
TouchEvent.prototype = {
/**
* @function
* @name pc.TouchEvent#getTouchById
* @description Get an event from one of the touch lists by the id. It is useful to access
* touches by their id so that you can be sure you are referencing the same touch.
* @param {Number} id The identifier of the touch.
* @param {pc.Touch[]} list An array of touches to search.
* @returns {pc.Touch} The {@link pc.Touch} object or null.
*/
getTouchById: function (id, list) {
var i, l = list.length;
for (i = 0; i < l; i++) {
if (list[i].id === id) {
return list[i];
}
}
return null;
}
};
/**
* @name pc.Touch
* @class A instance of a single point touch on a {@link pc.TouchDevice}
* @description Create a new Touch object from the browser Touch
* @param {Touch} touch The browser Touch object
* @property {Number} id The identifier of the touch
* @property {Number} x The x co-ordinate relative to the element that the TouchDevice is attached to
* @property {Number} y The y co-ordinate relative to the element that the TouchDevice is attached to
* @property {Element} target The target element of the touch event
* @property {Touch} touch The original browser Touch object
*/
var Touch = function (touch) {
var coords = pc.getTouchTargetCoords(touch);
this.id = touch.identifier;
this.x = coords.x;
this.y = coords.y;
this.target = touch.target;
this.touch = touch;
};
/**
* @name pc.TouchDevice
* @class Attach a TouchDevice to an element and it will receive and fire events when the element is touched.
* See also {@link pc.Touch} and {@link pc.TouchEvent}
* @description Create a new touch device and attach it to an element
* @param {Element} element The element to attach listen for events on
*/
var TouchDevice = function (element) {
this._startHandler = this._handleTouchStart.bind(this);
this._endHandler = this._handleTouchEnd.bind(this);
this._moveHandler = this._handleTouchMove.bind(this);
this._cancelHandler = this._handleTouchCancel.bind(this);
this.attach(element);
pc.events.attach(this);
};
TouchDevice.prototype = {
/**
* @function
* @name pc.TouchDevice#attach
* @description Attach a device to an element in the DOM.
* If the device is already attached to an element this method will detach it first
* @param {Element} element The element to attach to
*/
attach: function (element) {
if (this._element) {
this.detach();
}
this._element = element;
this._element.addEventListener('touchstart', this._startHandler, false);
this._element.addEventListener('touchend', this._endHandler, false);
this._element.addEventListener('touchmove', this._moveHandler, false);
this._element.addEventListener('touchcancel', this._cancelHandler, false);
},
/**
* @function
* @name pc.TouchDevice#detach
* @description Detach a device from the element it is attached to
*/
detach: function () {
if (this._element) {
this._element.removeEventListener('touchstart', this._startHandler, false);
this._element.removeEventListener('touchend', this._endHandler, false);
this._element.removeEventListener('touchmove', this._moveHandler, false);
this._element.removeEventListener('touchcancel', this._cancelHandler, false);
}
this._element = null;
},
_handleTouchStart: function (e) {
this.fire('touchstart', new TouchEvent(this, e));
},
_handleTouchEnd: function (e) {
this.fire('touchend', new TouchEvent(this, e));
},
_handleTouchMove: function (e) {
// call preventDefault to avoid issues in Chrome Android:
// http://wilsonpage.co.uk/touch-events-in-chrome-android/
e.preventDefault();
this.fire('touchmove', new TouchEvent(this, e));
},
_handleTouchCancel: function (e) {
this.fire('touchcancel', new TouchEvent(this, e));
}
};
return {
/**
* @function
* @name pc.getTouchTargetCoords
* @description Similiar to {@link pc.getTargetCoords} for the MouseEvents.
* This function takes a browser Touch object and returns the co-ordinates of the
* touch relative to the target element.
* @param {Touch} touch The browser Touch object
* @returns {Object} The co-ordinates of the touch relative to the touch.target element. In the format {x, y}
*/
getTouchTargetCoords: function (touch) {
var totalOffsetX = 0;
var totalOffsetY = 0;
var target = touch.target;
while (!(target instanceof HTMLElement)) {
target = target.parentNode;
}
var currentElement = target;
do {
totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
currentElement = currentElement.offsetParent;
} while (currentElement);
return {
x: touch.pageX - totalOffsetX,
y: touch.pageY - totalOffsetY
};
},
TouchDevice: TouchDevice,
TouchEvent: TouchEvent
};
}());