weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
822 lines (738 loc) • 34.3 kB
JavaScript
;(function(fn) {
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = fn();
} else if (typeof define === "function") {
define("universal-panresponder", function(require, exports, module){
module.exports = fn();
});
} else {
var root;
if (typeof window !== "undefined") {
root = window;
} else if (typeof self !== "undefined") {
root = self;
} else if (typeof global !== "undefined") {
root = global;
} else {
// NOTICE: In JavaScript strict mode, this is null
root = this;
}
root["UniversalPanresponder"] = fn();
}
})(function(){
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
;
var _universalEnv = __webpack_require__(1);
var _TouchHistoryMath = __webpack_require__(2);
var _TouchHistoryMath2 = _interopRequireDefault(_TouchHistoryMath);
var _ResponderTouchHistoryStore = __webpack_require__(3);
var _ResponderTouchHistoryStore2 = _interopRequireDefault(_ResponderTouchHistoryStore);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var currentCentroidXOfTouchesChangedAfter = _TouchHistoryMath2.default.currentCentroidXOfTouchesChangedAfter;
var currentCentroidYOfTouchesChangedAfter = _TouchHistoryMath2.default.currentCentroidYOfTouchesChangedAfter;
var previousCentroidXOfTouchesChangedAfter = _TouchHistoryMath2.default.previousCentroidXOfTouchesChangedAfter;
var previousCentroidYOfTouchesChangedAfter = _TouchHistoryMath2.default.previousCentroidYOfTouchesChangedAfter;
var currentCentroidX = _TouchHistoryMath2.default.currentCentroidX;
var currentCentroidY = _TouchHistoryMath2.default.currentCentroidY;
/**
* `PanResponder` reconciles several touches into a single gesture. It makes
* single-touch gestures resilient to extra touches, and can be used to
* recognize simple multi-touch gestures.
*
* By default, `PanResponder` holds an `InteractionManager handle to block
* long-running JS events from interrupting active gestures.
*
* It provides a predictable wrapper of the responder handlers provided by the
* [gesture responder system](docs/gesture-responder-system.html).
* For each handler, it provides a new `gestureState` object alongside the
* native event object:
*
* ```
* onPanResponderMove: (event, gestureState) => {}
* ```
*
* A native event is a synthetic touch event with the following form:
*
* - `nativeEvent`
* + `changedTouches` - Array of all touch events that have changed since the last event
* + `identifier` - The ID of the touch
* + `locationX` - The X position of the touch, relative to the element
* + `locationY` - The Y position of the touch, relative to the element
* + `pageX` - The X position of the touch, relative to the root element
* + `pageY` - The Y position of the touch, relative to the root element
* + `target` - The node id of the element receiving the touch event
* + `timestamp` - A time identifier for the touch, useful for velocity calculation
* + `touches` - Array of all current touches on the screen
*
* A `gestureState` object has the following:
*
* - `stateID` - ID of the gestureState- persisted as long as there at least
* one touch on screen
* - `moveX` - the latest screen coordinates of the recently-moved touch
* - `moveY` - the latest screen coordinates of the recently-moved touch
* - `x0` - the screen coordinates of the responder grant
* - `y0` - the screen coordinates of the responder grant
* - `dx` - accumulated distance of the gesture since the touch started
* - `dy` - accumulated distance of the gesture since the touch started
* - `vx` - current velocity of the gesture
* - `vy` - current velocity of the gesture
* - `numberActiveTouches` - Number of touches currently on screen
*
* ### Basic Usage
*
* ```
* componentWillMount: function() {
* this._panResponder = PanResponder.create({
* // Ask to be the responder:
* onStartShouldSetPanResponder: (evt, gestureState) => true,
* onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
* onMoveShouldSetPanResponder: (evt, gestureState) => true,
* onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
*
* onPanResponderGrant: (evt, gestureState) => {
* // The guesture has started. Show visual feedback so the user knows
* // what is happening!
*
* // gestureState.{x,y}0 will be set to zero now
* },
* onPanResponderMove: (evt, gestureState) => {
* // The most recent move distance is gestureState.move{X,Y}
*
* // The accumulated gesture distance since becoming responder is
* // gestureState.d{x,y}
* },
* onPanResponderTerminationRequest: (evt, gestureState) => true,
* onPanResponderRelease: (evt, gestureState) => {
* // The user has released all touches while this view is the
* // responder. This typically means a gesture has succeeded
* },
* onPanResponderTerminate: (evt, gestureState) => {
* // Another component has become the responder, so this gesture
* // should be cancelled
* },
* onShouldBlockNativeResponder: (evt, gestureState) => {
* // Returns whether this component should block native components from becoming the JS
* // responder. Returns true by default. Is currently only supported on android.
* return true;
* },
* });
* },
*
* render: function() {
* return (
* <View {...this._panResponder.panHandlers} />
* );
* },
*
* ```
*
* ### Working Example
*
* To see it in action, try the
* [PanResponder example in UIExplorer](https://github.com/facebook/react-native/blob/master/Examples/UIExplorer/PanResponderExample.js)
*/
var PanResponder = {
/**
*
* A graphical explanation of the touch data flow:
*
* +----------------------------+ +--------------------------------+
* | ResponderTouchHistoryStore | |TouchHistoryMath |
* +----------------------------+ +----------+---------------------+
* |Global store of touchHistory| |Allocation-less math util |
* |including activeness, start | |on touch history (centroids |
* |position, prev/cur position.| |and multitouch movement etc) |
* | | | |
* +----^-----------------------+ +----^---------------------------+
* | |
* | (records relevant history |
* | of touches relevant for |
* | implementing higher level |
* | gestures) |
* | |
* +----+-----------------------+ +----|---------------------------+
* | ResponderEventPlugin | | | Your App/Component |
* +----------------------------+ +----|---------------------------+
* |Negotiates which view gets | Low level | | High level |
* |onResponderMove events. | events w/ | +-+-------+ events w/ |
* |Also records history into | touchHistory| | Pan | multitouch + |
* |ResponderTouchHistoryStore. +---------------->Responder+-----> accumulative|
* +----------------------------+ attached to | | | distance and |
* each event | +---------+ velocity. |
* | |
* | |
* +--------------------------------+
*
*
*
* Gesture that calculates cumulative movement over time in a way that just
* "does the right thing" for multiple touches. The "right thing" is very
* nuanced. When moving two touches in opposite directions, the cumulative
* distance is zero in each dimension. When two touches move in parallel five
* pixels in the same direction, the cumulative distance is five, not ten. If
* two touches start, one moves five in a direction, then stops and the other
* touch moves fives in the same direction, the cumulative distance is ten.
*
* This logic requires a kind of processing of time "clusters" of touch events
* so that two touch moves that essentially occur in parallel but move every
* other frame respectively, are considered part of the same movement.
*
* Explanation of some of the non-obvious fields:
*
* - moveX/moveY: If no move event has been observed, then `(moveX, moveY)` is
* invalid. If a move event has been observed, `(moveX, moveY)` is the
* centroid of the most recently moved "cluster" of active touches.
* (Currently all move have the same timeStamp, but later we should add some
* threshold for what is considered to be "moving"). If a palm is
* accidentally counted as a touch, but a finger is moving greatly, the palm
* will move slightly, but we only want to count the single moving touch.
* - x0/y0: Centroid location (non-cumulative) at the time of becoming
* responder.
* - dx/dy: Cumulative touch distance - not the same thing as sum of each touch
* distance. Accounts for touch moves that are clustered together in time,
* moving the same direction. Only valid when currently responder (otherwise,
* it only represents the drag distance below the threshold).
* - vx/vy: Velocity.
*/
_initializeGestureState: function _initializeGestureState(gestureState) {
gestureState.moveX = 0;
gestureState.moveY = 0;
gestureState.x0 = 0;
gestureState.y0 = 0;
gestureState.dx = 0;
gestureState.dy = 0;
gestureState.vx = 0;
gestureState.vy = 0;
gestureState.numberActiveTouches = 0;
// All `gestureState` accounts for timeStamps up until:
gestureState._accountsForMovesUpTo = 0;
},
/**
* This is nuanced and is necessary. It is incorrect to continuously take all
* active *and* recently moved touches, find the centroid, and track how that
* result changes over time. Instead, we must take all recently moved
* touches, and calculate how the centroid has changed just for those
* recently moved touches, and append that change to an accumulator. This is
* to (at least) handle the case where the user is moving three fingers, and
* then one of the fingers stops but the other two continue.
*
* This is very different than taking all of the recently moved touches and
* storing their centroid as `dx/dy`. For correctness, we must *accumulate
* changes* in the centroid of recently moved touches.
*
* There is also some nuance with how we handle multiple moved touches in a
* single event. With the way `ReactNativeEventEmitter` dispatches touches as
* individual events, multiple touches generate two 'move' events, each of
* them triggering `onResponderMove`. But with the way `PanResponder` works,
* all of the gesture inference is performed on the first dispatch, since it
* looks at all of the touches (even the ones for which there hasn't been a
* native dispatch yet). Therefore, `PanResponder` does not call
* `onResponderMove` passed the first dispatch. This diverges from the
* typical responder callback pattern (without using `PanResponder`), but
* avoids more dispatches than necessary.
*/
_updateGestureStateOnMove: function _updateGestureStateOnMove(gestureState, touchHistory) {
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
gestureState.moveX = currentCentroidXOfTouchesChangedAfter(touchHistory, gestureState._accountsForMovesUpTo);
gestureState.moveY = currentCentroidYOfTouchesChangedAfter(touchHistory, gestureState._accountsForMovesUpTo);
var movedAfter = gestureState._accountsForMovesUpTo;
var prevX = previousCentroidXOfTouchesChangedAfter(touchHistory, movedAfter);
var x = currentCentroidXOfTouchesChangedAfter(touchHistory, movedAfter);
var prevY = previousCentroidYOfTouchesChangedAfter(touchHistory, movedAfter);
var y = currentCentroidYOfTouchesChangedAfter(touchHistory, movedAfter);
var nextDX = gestureState.dx + (x - prevX);
var nextDY = gestureState.dy + (y - prevY);
// TODO: This must be filtered intelligently.
var dt = touchHistory.mostRecentTimeStamp - gestureState._accountsForMovesUpTo;
gestureState.vx = (nextDX - gestureState.dx) / dt;
gestureState.vy = (nextDY - gestureState.dy) / dt;
gestureState.dx = nextDX;
gestureState.dy = nextDY;
gestureState._accountsForMovesUpTo = touchHistory.mostRecentTimeStamp;
},
/**
* @param {object} config Enhanced versions of all of the responder callbacks
* that provide not only the typical `ResponderSyntheticEvent`, but also the
* `PanResponder` gesture state. Simply replace the word `Responder` with
* `PanResponder` in each of the typical `onResponder*` callbacks. For
* example, the `config` object would look like:
*
* - `onMoveShouldSetPanResponder: (e, gestureState) => {...}`
* - `onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}`
* - `onStartShouldSetPanResponder: (e, gestureState) => {...}`
* - `onStartShouldSetPanResponderCapture: (e, gestureState) => {...}`
* - `onPanResponderReject: (e, gestureState) => {...}`
* - `onPanResponderGrant: (e, gestureState) => {...}`
* - `onPanResponderStart: (e, gestureState) => {...}`
* - `onPanResponderEnd: (e, gestureState) => {...}`
* - `onPanResponderRelease: (e, gestureState) => {...}`
* - `onPanResponderMove: (e, gestureState) => {...}`
* - `onPanResponderTerminate: (e, gestureState) => {...}`
* - `onPanResponderTerminationRequest: (e, gestureState) => {...}`
* - `onShouldBlockNativeResponder: (e, gestureState) => {...}`
*
* In general, for events that have capture equivalents, we update the
* gestureState once in the capture phase and can use it in the bubble phase
* as well.
*
* Be careful with onStartShould* callbacks. They only reflect updated
* `gestureState` for start/end events that bubble/capture to the Node.
* Once the node is the responder, you can rely on every start/end event
* being processed by the gesture and `gestureState` being updated
* accordingly. (numberActiveTouches) may not be totally accurate unless you
* are the responder.
*/
create: function create(config) {
var gestureState = {
// Useful for debugging
stateID: Math.random()
};
PanResponder._initializeGestureState(gestureState);
var setHandlers = {
// Ask to be the responder:
onStartShouldSetResponder: function onStartShouldSetResponder(e) {
return config.onStartShouldSetPanResponder === undefined ? false : config.onStartShouldSetPanResponder(e, gestureState);
},
onMoveShouldSetResponder: function onMoveShouldSetResponder(e) {
return config.onMoveShouldSetPanResponder === undefined ? false : config.onMoveShouldSetPanResponder(e, gestureState);
},
onStartShouldSetResponderCapture: function onStartShouldSetResponderCapture(e) {
// TODO: Actually, we should reinitialize the state any time
// touches.length increases from 0 active to > 0 active.
if (e.nativeEvent.touches.length === 1) {
PanResponder._initializeGestureState(gestureState);
}
gestureState.numberActiveTouches = _ResponderTouchHistoryStore2.default.touchHistory.numberActiveTouches;
return config.onStartShouldSetPanResponderCapture !== undefined ? config.onStartShouldSetPanResponderCapture(e, gestureState) : false;
},
onMoveShouldSetResponderCapture: function onMoveShouldSetResponderCapture(e) {
var touchHistory = _ResponderTouchHistoryStore2.default.touchHistory;
// Responder system incorrectly dispatches should* to current responder
// Filter out any touch moves past the first one - we would have
// already processed multi-touch geometry during the first event.
if (gestureState._accountsForMovesUpTo === touchHistory.mostRecentTimeStamp) {
return false;
}
PanResponder._updateGestureStateOnMove(gestureState, touchHistory);
return config.onMoveShouldSetPanResponderCapture ? config.onMoveShouldSetPanResponderCapture(e, gestureState) : false;
}
};
var responderHandlers = {
onResponderGrant: function onResponderGrant(e) {
gestureState.x0 = currentCentroidX(_ResponderTouchHistoryStore2.default.touchHistory);
gestureState.y0 = currentCentroidY(_ResponderTouchHistoryStore2.default.touchHistory);
gestureState.dx = 0;
gestureState.dy = 0;
if (config.onPanResponderGrant) {
config.onPanResponderGrant(e, gestureState);
}
// TODO: t7467124 investigate if this can be removed
return config.onShouldBlockNativeResponder === undefined ? true : config.onShouldBlockNativeResponder();
},
onResponderReject: function onResponderReject(e) {
config.onPanResponderReject && config.onPanResponderReject(e, gestureState);
},
onResponderRelease: function onResponderRelease(e) {
config.onPanResponderRelease && config.onPanResponderRelease(e, gestureState);
PanResponder._initializeGestureState(gestureState);
},
onResponderTerminate: function onResponderTerminate(e) {
config.onPanResponderTerminate && config.onPanResponderTerminate(e, gestureState);
PanResponder._initializeGestureState(gestureState);
},
onResponderTerminationRequest: function onResponderTerminationRequest(e) {
return config.onPanResponderTerminationRequest === undefined ? true : config.onPanResponderTerminationRequest(e, gestureState);
}
};
// Track for mouse event
var isPanStart = false;
// Default
var panHandlers = {
onTouchStart: function onTouchStart(e) {
isPanStart = true;
_ResponderTouchHistoryStore2.default.recordTouchTrack('start', e);
responderHandlers.onResponderGrant(e);
var touchHistory = _ResponderTouchHistoryStore2.default.touchHistory;
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
if (!setHandlers.onStartShouldSetResponder(e)) {
return responderHandlers.onResponderReject(e);
}
if (config.onPanResponderStart) {
config.onPanResponderStart(e, gestureState);
}
},
onTouchMove: function onTouchMove(e) {
if (!isPanStart) return;
_ResponderTouchHistoryStore2.default.recordTouchTrack('move', e);
var touchHistory = _ResponderTouchHistoryStore2.default.touchHistory;
// Guard against the dispatch of two touch moves when there are two
// simultaneously changed touches.
if (gestureState._accountsForMovesUpTo === touchHistory.mostRecentTimeStamp) {
return;
}
// Filter out any touch moves past the first one - we would have
// already processed multi-touch geometry during the first event.
PanResponder._updateGestureStateOnMove(gestureState, touchHistory);
if (!setHandlers.onMoveShouldSetResponder(e)) {
return;
}
if (config.onPanResponderMove) {
config.onPanResponderMove(e, gestureState);
}
},
onTouchEnd: function onTouchEnd(e) {
isPanStart = false;
_ResponderTouchHistoryStore2.default.recordTouchTrack('end', e);
var touchHistory = _ResponderTouchHistoryStore2.default.touchHistory;
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
if (config.onPanResponderEnd) {
config.onPanResponderEnd(e, gestureState);
}
responderHandlers.onResponderRelease(e);
}
};
if (_universalEnv.isWeb) {
if ('ontouchstart' in window) {
panHandlers = {
onTouchStart: panHandlers.onTouchStart,
onTouchMove: panHandlers.onTouchMove,
onTouchEnd: panHandlers.onTouchEnd
};
} else {
panHandlers = {
onMouseDown: panHandlers.onTouchStart,
onMouseMove: panHandlers.onTouchMove,
onMouseUp: panHandlers.onTouchEnd
};
}
}
return { panHandlers: panHandlers };
}
};
module.exports = PanResponder;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
;
var _typeof2 = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
return typeof obj === "undefined" ? "undefined" : _typeof2(obj);
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof2(obj);
};
// https://www.w3.org/TR/html5/webappapis.html#dom-navigator-appcodename
var isWeb = exports.isWeb = (typeof navigator === 'undefined' ? 'undefined' : _typeof(navigator)) === 'object' && (navigator.appCodeName === 'Mozilla' || navigator.product === 'Gecko');
var isNode = exports.isNode = typeof process !== 'undefined' && !!(process.versions && process.versions.node);
var isWeex = exports.isWeex = typeof callNative === 'function';
var isReactNative = exports.isReactNative = typeof __fbBatchedBridgeConfig !== 'undefined';
exports['default'] = module.exports;
exports.default = module.exports;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
;
var TouchHistoryMath = {
/**
* This code is optimized and not intended to look beautiful. This allows
* computing of touch centroids that have moved after `touchesChangedAfter`
* timeStamp. You can compute the current centroid involving all touches
* moves after `touchesChangedAfter`, or you can compute the previous
* centroid of all touches that were moved after `touchesChangedAfter`.
*
* @param {TouchHistoryMath} touchHistory Standard Responder touch track
* data.
* @param {number} touchesChangedAfter timeStamp after which moved touches
* are considered "actively moving" - not just "active".
* @param {boolean} isXAxis Consider `x` dimension vs. `y` dimension.
* @param {boolean} ofCurrent Compute current centroid for actively moving
* touches vs. previous centroid of now actively moving touches.
* @return {number} value of centroid in specified dimension.
*/
centroidDimension: function centroidDimension(touchHistory, touchesChangedAfter, isXAxis, ofCurrent) {
var touchBank = touchHistory.touchBank;
var total = 0;
var count = 0;
var oneTouchData = touchHistory.numberActiveTouches === 1 ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] : null;
if (oneTouchData !== null) {
if (oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter) {
total += ofCurrent && isXAxis ? oneTouchData.currentPageX : ofCurrent && !isXAxis ? oneTouchData.currentPageY : !ofCurrent && isXAxis ? oneTouchData.previousPageX : oneTouchData.previousPageY;
count = 1;
}
} else {
for (var i in touchBank) {
var touchTrack = touchBank[i];
if (touchTrack !== null && touchTrack !== undefined && touchTrack.touchActive && touchTrack.currentTimeStamp >= touchesChangedAfter) {
var toAdd; // Yuck, program temporarily in invalid state.
if (ofCurrent && isXAxis) {
toAdd = touchTrack.currentPageX;
} else if (ofCurrent && !isXAxis) {
toAdd = touchTrack.currentPageY;
} else if (!ofCurrent && isXAxis) {
toAdd = touchTrack.previousPageX;
} else {
toAdd = touchTrack.previousPageY;
}
total += toAdd;
count++;
}
}
}
return count > 0 ? total / count : TouchHistoryMath.noCentroid;
},
currentCentroidXOfTouchesChangedAfter: function currentCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, true, // isXAxis
true // ofCurrent
);
},
currentCentroidYOfTouchesChangedAfter: function currentCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, false, // isXAxis
true // ofCurrent
);
},
previousCentroidXOfTouchesChangedAfter: function previousCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, true, // isXAxis
false // ofCurrent
);
},
previousCentroidYOfTouchesChangedAfter: function previousCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
return TouchHistoryMath.centroidDimension(touchHistory, touchesChangedAfter, false, // isXAxis
false // ofCurrent
);
},
currentCentroidX: function currentCentroidX(touchHistory) {
return TouchHistoryMath.centroidDimension(touchHistory, 0, // touchesChangedAfter
true, // isXAxis
true // ofCurrent
);
},
currentCentroidY: function currentCentroidY(touchHistory) {
return TouchHistoryMath.centroidDimension(touchHistory, 0, // touchesChangedAfter
false, // isXAxis
true // ofCurrent
);
},
noCentroid: -1
};
module.exports = TouchHistoryMath;
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
;
/**
* Touch position/time tracking information by touchID. Typically, we'll only
* see IDs with a range of 1-20 (they are recycled when touches end and then
* start again). This data is commonly needed by many different interaction
* logic modules so precomputing it is very helpful to do once.
* Each touch object in `touchBank` is of the following form:
* { touchActive: boolean,
* startTimeStamp: number,
* startPageX: number,
* startPageY: number,
* currentPageX: number,
* currentPageY: number,
* currentTimeStamp: number
* }
*/
var touchHistory = {
touchBank: {},
numberActiveTouches: 0,
// If there is only one active touch, we remember its location. This prevents
// us having to loop through all of the touches all the time in the most
// common case.
indexOfSingleActiveTouch: -1,
mostRecentTimeStamp: 0
};
/**
* TODO: Instead of making gestures recompute filtered velocity, we could
* include a built in velocity computation that can be reused globally.
* @param {Touch} touch Native touch object.
*/
var initializeTouchData = function initializeTouchData(touch) {
return {
touchActive: true,
startTimeStamp: touch.timestamp,
startPageX: touch.pageX,
startPageY: touch.pageY,
currentPageX: touch.pageX,
currentPageY: touch.pageY,
currentTimeStamp: touch.timestamp,
previousPageX: touch.pageX,
previousPageY: touch.pageY,
previousTimeStamp: touch.timestamp
};
};
var reinitializeTouchTrack = function reinitializeTouchTrack(touchTrack, touch) {
touchTrack.touchActive = true;
touchTrack.startTimeStamp = touch.timestamp;
touchTrack.startPageX = touch.pageX;
touchTrack.startPageY = touch.pageY;
touchTrack.currentPageX = touch.pageX;
touchTrack.currentPageY = touch.pageY;
touchTrack.currentTimeStamp = touch.timestamp;
touchTrack.previousPageX = touch.pageX;
touchTrack.previousPageY = touch.pageY;
touchTrack.previousTimeStamp = touch.timestamp;
};
var recordStartTouchData = function recordStartTouchData(touch) {
var touchBank = touchHistory.touchBank;
var identifier = touch.identifier;
var touchTrack = touchBank[identifier];
if (touchTrack) {
reinitializeTouchTrack(touchTrack, touch);
} else {
touchBank[touch.identifier] = initializeTouchData(touch);
}
touchHistory.mostRecentTimeStamp = touch.timestamp;
};
var recordMoveTouchData = function recordMoveTouchData(touch) {
var touchBank = touchHistory.touchBank;
var touchTrack = touchBank[touch.identifier];
touchTrack.touchActive = true;
touchTrack.previousPageX = touchTrack.currentPageX;
touchTrack.previousPageY = touchTrack.currentPageY;
touchTrack.previousTimeStamp = touchTrack.currentTimeStamp;
touchTrack.currentPageX = touch.pageX;
touchTrack.currentPageY = touch.pageY;
touchTrack.currentTimeStamp = touch.timestamp;
touchHistory.mostRecentTimeStamp = touch.timestamp;
};
var recordEndTouchData = function recordEndTouchData(touch) {
var touchBank = touchHistory.touchBank;
var touchTrack = touchBank[touch.identifier];
touchTrack.previousPageX = touchTrack.currentPageX;
touchTrack.previousPageY = touchTrack.currentPageY;
touchTrack.previousTimeStamp = touchTrack.currentTimeStamp;
touchTrack.currentPageX = touch.pageX;
touchTrack.currentPageY = touch.pageY;
touchTrack.currentTimeStamp = touch.timestamp;
touchTrack.touchActive = false;
touchHistory.mostRecentTimeStamp = touch.timestamp;
};
function toArray(collection) {
return collection && Array.prototype.slice.call(collection) || [];
}
function normalizeTouches(touches, nativeEvent) {
// Weex is timestamp
var timeStamp = nativeEvent.timeStamp || nativeEvent.timestamp;
return toArray(touches).map(function (touch) {
// Cloned touch
return {
clientX: touch.clientX,
clientY: touch.clientY,
force: touch.force,
// FIXME: In weex android pageX/Y return a error value
pageX: touch.screenX,
pageY: touch.screenY,
radiusX: touch.radiusX,
radiusY: touch.radiusY,
rotationAngle: touch.rotationAngle,
screenX: touch.screenX,
screenY: touch.screenY,
target: touch.target || nativeEvent.target,
timestamp: timeStamp,
identifier: touch.identifier || 1 // MouseEvent without identifier
};
});
};
var ResponderTouchHistoryStore = {
recordTouchTrack: function recordTouchTrack(topLevelType, nativeEvent) {
var touchBank = touchHistory.touchBank;
var changedTouches = normalizeTouches(nativeEvent.changedTouches || [nativeEvent], nativeEvent);
if (topLevelType === 'move') {
changedTouches.forEach(recordMoveTouchData);
} else if (topLevelType === 'start') {
changedTouches.forEach(recordStartTouchData);
touchHistory.numberActiveTouches = changedTouches.length;
if (touchHistory.numberActiveTouches === 1) {
touchHistory.indexOfSingleActiveTouch = changedTouches[0].identifier;
}
} else if (topLevelType === 'end') {
changedTouches.forEach(recordEndTouchData);
touchHistory.numberActiveTouches = changedTouches.length;
if (touchHistory.numberActiveTouches === 1) {
for (var i in touchBank) {
var touchTrackToCheck = touchBank[i];
if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
touchHistory.indexOfSingleActiveTouch = i;
break;
}
}
}
}
},
touchHistory: touchHistory
};
module.exports = ResponderTouchHistoryStore;
/***/ })
/******/ ])});;
//# sourceMappingURL=panresponder.map