UNPKG

weex-nuke

Version:

基于 Rax 、Weex 的高性能组件体系 ~~

800 lines (717 loc) 33.7 kB
module.exports = function(require, exports, module) { with(this) { module.exports = /******/ (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__) { "use strict"; 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__) { "use strict"; 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__) { "use strict"; 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__) { "use strict"; /** * 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.factory.map