Add support for device swipe events
Summary:
Ref T2700. Allow JS to listen for swipes on devices.
There are a bunch of tricky cases here and I probably didn't get them all totally right, but this interaction broadly looks like this:
- We implement gesture recognition for the mouse in device modes (narrow browser), and for touch events from an actual device.
- The sigil `touchable` indicates that a node wants to react to touch events.
- When the user touches a `touchable` node, we start listening for moves. They might be tapping/clicking (in which case we don't care), but they might also be gesturing.
- Once the user moves their finger/pointer far enough away from the tap origin, we recognize it as a gesture. I hardcoded this at 20px; I wasn't able to find any "official" Apple value, but 20px seems like a common default.
- At this point, we look at where their finger has moved.
- If they moved it mostly up/down, we interpret the gesture as "scroll" and just stop listening. The device does its own thing.
- However, if they moved it mostly left/right, we interpret it as a "swipe". We start killing the moves so the device doesn't scroll.
- Once we've recognized that a gesture is underway, we send a "gesture.swipe.start" event and then "gesture.swipe.move" events for every move.
- When the user ends the gesture, we send "gesture.swipe.end".
- If the user cancels the gesture (currently, only by tapping with a second finger), we send "gesture.swipe.cancel".
- Gesture events have raw position data and some convenience fields.
Test Plan:
Wrote UI example and used it from the Desktop, iPhone simulator, and a real iphone.
- The code always seems to get "scroll" vs "swipe" correct (i.e., consistent with my intentions).
- The threshold feels pretty good to me.
- Tapping with a second finger cancels the action.
Reviewers: chad, btrahan
Reviewed By: chad
CC: aran
Maniphest Tasks: T2700
Differential Revision: https://secure.phabricator.com/D5308
2013-03-09 22:53:15 +01:00
|
|
|
/**
|
|
|
|
* @requires javelin-stratcom
|
|
|
|
* javelin-behavior
|
|
|
|
* javelin-vector
|
|
|
|
* javelin-dom
|
|
|
|
* @provides javelin-behavior-phabricator-gesture-example
|
|
|
|
*/
|
|
|
|
|
|
|
|
JX.behavior('phabricator-gesture-example', function(config) {
|
|
|
|
|
|
|
|
var strokes = [];
|
|
|
|
var current = [];
|
|
|
|
|
|
|
|
var root = JX.$(config.rootID);
|
|
|
|
|
|
|
|
var canvas = JX.$N('canvas');
|
|
|
|
var d = JX.Vector.getDim(root);
|
|
|
|
canvas.width = d.x;
|
|
|
|
canvas.height = d.y;
|
|
|
|
root.appendChild(canvas);
|
|
|
|
|
|
|
|
var cxt = canvas.getContext('2d');
|
|
|
|
JX.Stratcom.listen(
|
|
|
|
'gesture.swipe.end',
|
|
|
|
null,
|
|
|
|
function(e) {
|
|
|
|
var stroke = get_stroke(e);
|
|
|
|
strokes.push(stroke);
|
|
|
|
current = [];
|
|
|
|
redraw();
|
|
|
|
});
|
|
|
|
|
|
|
|
JX.Stratcom.listen(
|
|
|
|
'gesture.swipe.move',
|
|
|
|
null,
|
|
|
|
function(e) {
|
|
|
|
var stroke = get_stroke(e);
|
|
|
|
current = [stroke];
|
|
|
|
redraw();
|
|
|
|
});
|
|
|
|
|
|
|
|
JX.Stratcom.listen(
|
|
|
|
'gesture.swipe.cancel',
|
|
|
|
null,
|
|
|
|
function(e) {
|
|
|
|
current = [];
|
|
|
|
redraw();
|
|
|
|
});
|
|
|
|
|
|
|
|
function get_stroke(e) {
|
|
|
|
var data = e.getData();
|
|
|
|
var p = JX.$V(root);
|
|
|
|
return [
|
|
|
|
data.p0.x - p.x,
|
|
|
|
data.p0.y - p.y,
|
|
|
|
data.p1.x - p.x,
|
|
|
|
data.p1.y - p.y
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
function redraw() {
|
|
|
|
cxt.fillStyle = '#dfdfdf';
|
|
|
|
cxt.fillRect(0, 0, d.x, d.y);
|
|
|
|
|
2013-05-19 02:04:22 +02:00
|
|
|
var s;
|
|
|
|
var ii;
|
|
|
|
for (ii = 0; ii < strokes.length; ii++) {
|
|
|
|
s = strokes[ii];
|
Add support for device swipe events
Summary:
Ref T2700. Allow JS to listen for swipes on devices.
There are a bunch of tricky cases here and I probably didn't get them all totally right, but this interaction broadly looks like this:
- We implement gesture recognition for the mouse in device modes (narrow browser), and for touch events from an actual device.
- The sigil `touchable` indicates that a node wants to react to touch events.
- When the user touches a `touchable` node, we start listening for moves. They might be tapping/clicking (in which case we don't care), but they might also be gesturing.
- Once the user moves their finger/pointer far enough away from the tap origin, we recognize it as a gesture. I hardcoded this at 20px; I wasn't able to find any "official" Apple value, but 20px seems like a common default.
- At this point, we look at where their finger has moved.
- If they moved it mostly up/down, we interpret the gesture as "scroll" and just stop listening. The device does its own thing.
- However, if they moved it mostly left/right, we interpret it as a "swipe". We start killing the moves so the device doesn't scroll.
- Once we've recognized that a gesture is underway, we send a "gesture.swipe.start" event and then "gesture.swipe.move" events for every move.
- When the user ends the gesture, we send "gesture.swipe.end".
- If the user cancels the gesture (currently, only by tapping with a second finger), we send "gesture.swipe.cancel".
- Gesture events have raw position data and some convenience fields.
Test Plan:
Wrote UI example and used it from the Desktop, iPhone simulator, and a real iphone.
- The code always seems to get "scroll" vs "swipe" correct (i.e., consistent with my intentions).
- The threshold feels pretty good to me.
- Tapping with a second finger cancels the action.
Reviewers: chad, btrahan
Reviewed By: chad
CC: aran
Maniphest Tasks: T2700
Differential Revision: https://secure.phabricator.com/D5308
2013-03-09 22:53:15 +01:00
|
|
|
cxt.strokeStyle = 'rgba(0, 0, 0, 0.50)';
|
|
|
|
cxt.beginPath();
|
|
|
|
cxt.moveTo(s[0], s[1]);
|
|
|
|
cxt.lineTo(s[2], s[3]);
|
|
|
|
cxt.stroke();
|
|
|
|
}
|
|
|
|
|
2013-05-19 02:04:22 +02:00
|
|
|
for (ii = 0; ii < current.length; ii++) {
|
|
|
|
s = current[ii];
|
Add support for device swipe events
Summary:
Ref T2700. Allow JS to listen for swipes on devices.
There are a bunch of tricky cases here and I probably didn't get them all totally right, but this interaction broadly looks like this:
- We implement gesture recognition for the mouse in device modes (narrow browser), and for touch events from an actual device.
- The sigil `touchable` indicates that a node wants to react to touch events.
- When the user touches a `touchable` node, we start listening for moves. They might be tapping/clicking (in which case we don't care), but they might also be gesturing.
- Once the user moves their finger/pointer far enough away from the tap origin, we recognize it as a gesture. I hardcoded this at 20px; I wasn't able to find any "official" Apple value, but 20px seems like a common default.
- At this point, we look at where their finger has moved.
- If they moved it mostly up/down, we interpret the gesture as "scroll" and just stop listening. The device does its own thing.
- However, if they moved it mostly left/right, we interpret it as a "swipe". We start killing the moves so the device doesn't scroll.
- Once we've recognized that a gesture is underway, we send a "gesture.swipe.start" event and then "gesture.swipe.move" events for every move.
- When the user ends the gesture, we send "gesture.swipe.end".
- If the user cancels the gesture (currently, only by tapping with a second finger), we send "gesture.swipe.cancel".
- Gesture events have raw position data and some convenience fields.
Test Plan:
Wrote UI example and used it from the Desktop, iPhone simulator, and a real iphone.
- The code always seems to get "scroll" vs "swipe" correct (i.e., consistent with my intentions).
- The threshold feels pretty good to me.
- Tapping with a second finger cancels the action.
Reviewers: chad, btrahan
Reviewed By: chad
CC: aran
Maniphest Tasks: T2700
Differential Revision: https://secure.phabricator.com/D5308
2013-03-09 22:53:15 +01:00
|
|
|
cxt.strokeStyle = 'rgba(255, 0, 0, 1)';
|
|
|
|
cxt.beginPath();
|
|
|
|
cxt.moveTo(s[0], s[1]);
|
|
|
|
cxt.lineTo(s[2], s[3]);
|
|
|
|
cxt.stroke();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
redraw();
|
|
|
|
});
|