rmc-picker
Advanced tools
Comparing version 2.2.1 to 2.2.2
@@ -8,4 +8,4 @@ "use strict"; | ||
exports.easeInOutCubic = easeInOutCubic; | ||
var desiredFrames = 60; | ||
var millisecondsPerSecond = 1000; | ||
var DESIRED_FRAMES = 60; | ||
var MILLISECONDS_PER_SECOND = 1000; | ||
var running = {}; | ||
@@ -18,4 +18,4 @@ var counter = 1; | ||
var requestFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame; | ||
return function (callback, root) { | ||
requestFrame(callback, root); | ||
return function (callback) { | ||
requestFrame(callback); | ||
}; | ||
@@ -39,3 +39,3 @@ })(), | ||
// Start the animation. | ||
start: function start(stepCallback, verifyCallback, completedCallback, duration, easingMethod, r) { | ||
start: function start(stepCallback, verifyCallback, completedCallback, duration, easingMethod) { | ||
var start = Date.now(); | ||
@@ -46,7 +46,2 @@ var lastFrame = start; | ||
var id = counter++; | ||
var root = r; | ||
if (!root) { | ||
root = document.body; | ||
} | ||
// Compacting running db automatically every few new animations | ||
@@ -74,3 +69,3 @@ if (id % 20 === 0) { | ||
if (completedCallback) { | ||
completedCallback(desiredFrames - dropCounter / ((now - start) / millisecondsPerSecond), id, false); | ||
completedCallback(DESIRED_FRAMES - dropCounter / ((now - start) / MILLISECONDS_PER_SECOND), id, false); | ||
} | ||
@@ -83,3 +78,3 @@ return; | ||
if (render) { | ||
var droppedFrames = Math.round((now - lastFrame) / (millisecondsPerSecond / desiredFrames)) - 1; | ||
var droppedFrames = Math.round((now - lastFrame) / (MILLISECONDS_PER_SECOND / DESIRED_FRAMES)) - 1; | ||
for (var j = 0; j < Math.min(droppedFrames, 4); j++) { | ||
@@ -104,7 +99,7 @@ step(true); | ||
if (completedCallback) { | ||
completedCallback(desiredFrames - dropCounter / ((now - start) / millisecondsPerSecond), id, percent === 1 || duration === null); | ||
completedCallback(DESIRED_FRAMES - dropCounter / ((now - start) / MILLISECONDS_PER_SECOND), id, percent === 1 || duration === null); | ||
} | ||
} else if (render) { | ||
lastFrame = now; | ||
Animate.requestAnimationFrame(step, root); | ||
Animate.requestAnimationFrame(step); | ||
} | ||
@@ -116,3 +111,3 @@ }; | ||
// Init first step | ||
Animate.requestAnimationFrame(step, root); | ||
Animate.requestAnimationFrame(step); | ||
// Return unique animation ID | ||
@@ -119,0 +114,0 @@ return id; |
@@ -22,2 +22,13 @@ /* | ||
var DECELERATION_VELOCITY_RATE = 0.95; | ||
// How much velocity is required to keep the deceleration running | ||
var MIN_VELOCITY_TO_KEEP_DECELERATING = 0.5; | ||
var POSITION_MAX_LENGTH = 40; | ||
var MINIUM_TRACKING_FOR_SCROLL = 0; | ||
var MINIUM_TRACKING_FOR_DRAG = 5; | ||
var DEFAULT_ANIM_DURATION = 250; | ||
var TIME_FRAME = 100; | ||
// How much velocity is required to start the deceleration | ||
var MIN_VELOCITY_TO_START_DECELERATION = 4; | ||
function assign(to, from) { | ||
@@ -80,4 +91,17 @@ for (var key in from) { | ||
getInitialState: function getInitialState() { | ||
var selectedValueState = undefined; | ||
var _props = this.props; | ||
var selectedValue = _props.selectedValue; | ||
var defaultSelectedValue = _props.defaultSelectedValue; | ||
var children = _props.children; | ||
if (selectedValue !== undefined) { | ||
selectedValueState = selectedValue; | ||
} else if (defaultSelectedValue !== undefined) { | ||
selectedValueState = defaultSelectedValue; | ||
} else if (children.length) { | ||
selectedValueState = children[0].value; | ||
} | ||
return { | ||
selectedValue: this.props.selectedValue || this.props.defaultSelectedValue | ||
selectedValue: selectedValueState | ||
}; | ||
@@ -111,3 +135,2 @@ }, | ||
} else { | ||
// console.log('select'); | ||
this.select(this.state.selectedValue, false); | ||
@@ -123,10 +146,11 @@ } | ||
component.removeEventListener('touchend', this.onTouchEnd, false); | ||
this.clearAnim(); | ||
}, | ||
onTouchEnd: function onTouchEnd(e) { | ||
this.doTouchEnd(e.timeStamp); | ||
this.doTouchEnd(+e.timeStamp); | ||
}, | ||
onTouchMove: function onTouchMove(e) { | ||
this.doTouchMove(e.touches, e.timeStamp); | ||
this.doTouchMove(e.touches, +e.timeStamp); | ||
}, | ||
@@ -139,3 +163,3 @@ | ||
e.preventDefault(); | ||
this.doTouchStart(e.touches, e.timeStamp); | ||
this.doTouchStart(e.touches, +e.timeStamp); | ||
}, | ||
@@ -160,13 +184,21 @@ | ||
clearAnim: function clearAnim() { | ||
if (this.isDecelerating) { | ||
_Animate.Animate.stop(this.isDecelerating); | ||
this.isDecelerating = false; | ||
} | ||
if (this.isAnimating) { | ||
_Animate.Animate.stop(this.isAnimating); | ||
this.isAnimating = false; | ||
} | ||
}, | ||
init: function init() { | ||
// console.log('init'); | ||
assign(this, { | ||
isSingleTouch: false, | ||
isTracking: false, | ||
didDecelerationComplete: false, | ||
isGesturing: false, | ||
isDragging: false, | ||
isDecelerating: false, | ||
isAnimating: false, | ||
clientTop: 0, | ||
clientHeight: 0, | ||
@@ -179,8 +211,8 @@ contentHeight: 0, | ||
scheduledTop: 0, | ||
lastTouchTop: null, | ||
lastTouchMove: null, | ||
positions: null, | ||
minDecelerationScrollTop: null, | ||
maxDecelerationScrollTop: null, | ||
decelerationVelocityY: null | ||
lastTouchTop: 0, | ||
lastTouchMove: 0, | ||
positions: [], | ||
minDecelerationScrollTop: 0, | ||
maxDecelerationScrollTop: 0, | ||
decelerationVelocityY: 0 | ||
}); | ||
@@ -195,6 +227,2 @@ | ||
var rect = component.getBoundingClientRect(); | ||
this.clientTop = rect.top + component.clientTop || 0; | ||
this.setDimensions(component.clientHeight, content.offsetHeight); | ||
@@ -212,4 +240,2 @@ | ||
this.scrollTo(this.scrollTop, animate); | ||
this.fireValueChange(this.props.children[index].value); | ||
}, | ||
@@ -233,6 +259,3 @@ | ||
if (this.isDecelerating) { | ||
_Animate.Animate.stop(this.isDecelerating); | ||
this.isDecelerating = false; | ||
} | ||
this.clearAnim(); | ||
@@ -247,3 +270,3 @@ top = Math.round(top / this.itemHeight) * this.itemHeight; | ||
} | ||
this.publish(top, 250); | ||
this.publish(top, DEFAULT_ANIM_DURATION); | ||
}, | ||
@@ -270,61 +293,14 @@ | ||
doTouchStart: function doTouchStart(touches, ts) { | ||
var timeStamp = ts; | ||
if (touches.length === null) { | ||
throw new Error('Invalid touch list: ' + touches); | ||
} | ||
if (timeStamp instanceof Date) { | ||
timeStamp = timeStamp.valueOf(); | ||
} | ||
if (typeof timeStamp !== 'number') { | ||
throw new Error('Invalid timestamp value: ' + timeStamp); | ||
} | ||
this.interruptedAnimation = true; | ||
if (this.isDecelerating) { | ||
_Animate.Animate.stop(this.isDecelerating); | ||
this.isDecelerating = false; | ||
this.interruptedAnimation = true; | ||
} | ||
if (this.isAnimating) { | ||
_Animate.Animate.stop(this.isAnimating); | ||
this.isAnimating = false; | ||
this.interruptedAnimation = true; | ||
} | ||
// Use center point when dealing with two fingers | ||
var currentTouchTop = undefined; | ||
var isSingleTouch = touches.length === 1; | ||
if (isSingleTouch) { | ||
currentTouchTop = touches[0].pageY; | ||
} else { | ||
currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2; | ||
} | ||
this.initialTouchTop = currentTouchTop; | ||
this.lastTouchTop = currentTouchTop; | ||
doTouchStart: function doTouchStart(touches, timeStamp) { | ||
this.clearAnim(); | ||
this.initialTouchTop = this.lastTouchTop = touches[0].pageY; | ||
this.lastTouchMove = timeStamp; | ||
this.lastScale = 1; | ||
this.enableScrollY = !isSingleTouch; | ||
this.enableScrollY = false; | ||
this.isTracking = true; | ||
this.didDecelerationComplete = false; | ||
this.isDragging = !isSingleTouch; | ||
this.isSingleTouch = isSingleTouch; | ||
this.isDragging = false; | ||
this.positions = []; | ||
}, | ||
doTouchMove: function doTouchMove(touches, ts, scale) { | ||
var timeStamp = ts; | ||
if (touches.length === null) { | ||
throw new Error('Invalid touch list: ' + touches); | ||
} | ||
if (timeStamp instanceof Date) { | ||
timeStamp = timeStamp.valueOf(); | ||
} | ||
if (typeof timeStamp !== 'number') { | ||
throw new Error('Invalid timestamp value: ' + timeStamp); | ||
} | ||
doTouchMove: function doTouchMove(touches, timeStamp) { | ||
// Ignore event when tracking is not enabled (event might be outside of element) | ||
@@ -335,11 +311,4 @@ if (!this.isTracking) { | ||
var currentTouchTop = undefined; | ||
var currentTouchTop = touches[0].pageY; | ||
// Compute move based around of center of fingers | ||
if (touches.length === 2) { | ||
currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2; | ||
} else { | ||
currentTouchTop = touches[0].pageY; | ||
} | ||
var positions = this.positions; | ||
@@ -369,7 +338,7 @@ | ||
// Keep list from growing infinitely (holding min 10, max 20 measure points) | ||
if (positions.length > 40) { | ||
positions.splice(0, 20); | ||
if (positions.length > POSITION_MAX_LENGTH) { | ||
positions.splice(0, POSITION_MAX_LENGTH / 2); | ||
} | ||
// Track scroll movement for decleration | ||
// Track scroll movement for declaration | ||
positions.push(scrollTop, timeStamp); | ||
@@ -381,16 +350,9 @@ | ||
} else { | ||
var minimumTrackingForScroll = 0; | ||
var minimumTrackingForDrag = 5; | ||
var distanceY = Math.abs(currentTouchTop - this.initialTouchTop); | ||
this.enableScrollY = distanceY >= minimumTrackingForScroll; | ||
this.enableScrollY = distanceY >= MINIUM_TRACKING_FOR_SCROLL; | ||
positions.push(this.scrollTop, timeStamp); | ||
this.isDragging = this.enableScrollY && distanceY >= minimumTrackingForDrag; | ||
if (this.isDragging) { | ||
this.interruptedAnimation = false; | ||
} | ||
this.isDragging = this.enableScrollY && distanceY >= MINIUM_TRACKING_FOR_DRAG; | ||
} | ||
@@ -401,14 +363,5 @@ | ||
this.lastTouchMove = timeStamp; | ||
this.lastScale = scale; | ||
}, | ||
doTouchEnd: function doTouchEnd(ts) { | ||
var timeStamp = ts; | ||
if (timeStamp instanceof Date) { | ||
timeStamp = timeStamp.valueOf(); | ||
} | ||
if (typeof timeStamp !== 'number') { | ||
throw new Error('Invalid timestamp value: ' + timeStamp); | ||
} | ||
doTouchEnd: function doTouchEnd(timeStamp) { | ||
// Ignore event when tracking is not enabled (no touchstart event on element) | ||
@@ -431,3 +384,3 @@ // This is required as this listener ('touchmove') sits on the document and not on the element itself. | ||
// Verify that the last move detected was in some relevant time frame | ||
if (this.isSingleTouch && timeStamp - this.lastTouchMove <= 100) { | ||
if (timeStamp - this.lastTouchMove <= TIME_FRAME) { | ||
// Then figure out what the scroll position was about 100ms ago | ||
@@ -439,3 +392,3 @@ var positions = this.positions; | ||
// Move pointer to position measured 100ms ago | ||
for (var i = endPos; i > 0 && positions[i] > this.lastTouchMove - 100; i -= 2) { | ||
for (var i = endPos; i > 0 && positions[i] > this.lastTouchMove - TIME_FRAME; i -= 2) { | ||
startPos = i; | ||
@@ -454,7 +407,4 @@ } | ||
// How much velocity is required to start the deceleration | ||
var minVelocityToStartDeceleration = 4; | ||
// Verify that we have enough velocity to start deceleration | ||
if (Math.abs(this.decelerationVelocityY) > minVelocityToStartDeceleration) { | ||
if (Math.abs(this.decelerationVelocityY) > MIN_VELOCITY_TO_START_DECELERATION) { | ||
this.startDeceleration(timeStamp); | ||
@@ -534,9 +484,6 @@ } | ||
// How much velocity is required to keep the deceleration running | ||
var minVelocityToKeepDecelerating = 0.5; | ||
// Detect whether it's still worth to continue animating steps | ||
// If we are already slow enough to not being user perceivable anymore, we stop the whole process here. | ||
var verify = function verify() { | ||
var shouldContinue = Math.abs(_this2.decelerationVelocityY) >= minVelocityToKeepDecelerating; | ||
var shouldContinue = Math.abs(_this2.decelerationVelocityY) >= MIN_VELOCITY_TO_KEEP_DECELERATING; | ||
if (!shouldContinue) { | ||
@@ -578,3 +525,3 @@ _this2.didDecelerationComplete = true; | ||
} else { | ||
this.decelerationVelocityY *= 0.95; | ||
this.decelerationVelocityY *= DECELERATION_VELOCITY_RATE; | ||
} | ||
@@ -585,5 +532,5 @@ | ||
render: function render() { | ||
var _props = this.props; | ||
var children = _props.children; | ||
var prefixCls = _props.prefixCls; | ||
var _props2 = this.props; | ||
var children = _props2.children; | ||
var prefixCls = _props2.prefixCls; | ||
var selectedValue = this.state.selectedValue; | ||
@@ -590,0 +537,0 @@ |
{ | ||
"name": "rmc-picker", | ||
"version": "2.2.1", | ||
"version": "2.2.2", | ||
"description": "React Mobile Picker Component", | ||
@@ -30,3 +30,3 @@ "keywords": [ | ||
"config": { | ||
"port": 8000 | ||
"port": 8020 | ||
}, | ||
@@ -45,2 +45,3 @@ "scripts": { | ||
"devDependencies": { | ||
"array-tree-filter": "1.x", | ||
"expect.js": "0.3.x", | ||
@@ -47,0 +48,0 @@ "pre-commit": "1.x", |
25804
9
614