mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
perf(ripple): improve ripple perf
This commit is contained in:
@ -27,7 +27,7 @@ export class Animation {
|
|||||||
constructor(ele, opts={}) {
|
constructor(ele, opts={}) {
|
||||||
this.reset();
|
this.reset();
|
||||||
this._opts = extend({
|
this._opts = extend({
|
||||||
renderDelay: 36
|
renderDelay: 16
|
||||||
}, opts);
|
}, opts);
|
||||||
|
|
||||||
this.elements(ele);
|
this.elements(ele);
|
||||||
@ -238,15 +238,31 @@ export class Animation {
|
|||||||
// stage all animations and child animations at their starting point
|
// stage all animations and child animations at their starting point
|
||||||
self.stage();
|
self.stage();
|
||||||
|
|
||||||
|
let resolve;
|
||||||
|
let promise = new Promise(res => { resolve = res; });
|
||||||
|
|
||||||
|
function kickoff() {
|
||||||
// synchronously call all onPlay()'s before play()
|
// synchronously call all onPlay()'s before play()
|
||||||
self._onPlay();
|
self._onPlay();
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
beginPlay().then(() => {
|
beginPlay().then(() => {
|
||||||
self._onFinish();
|
self._onFinish();
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (self._duration > 16) {
|
||||||
|
// begin each animation when everything is rendered in their starting point
|
||||||
|
// give the browser some time to render everything in place before starting
|
||||||
|
setTimeout(kickoff, this._opts.renderDelay);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// no need to render everything in there place before animating in
|
||||||
|
// just kick it off immediately to render them in their "to" locations
|
||||||
|
kickoff();
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a child animation, it is told exactly when to
|
// this is a child animation, it is told exactly when to
|
||||||
@ -586,11 +602,13 @@ class Animate {
|
|||||||
// lock in where the element will stop at
|
// lock in where the element will stop at
|
||||||
// if the playbackRate is negative then it needs to return
|
// if the playbackRate is negative then it needs to return
|
||||||
// to its "from" effects
|
// to its "from" effects
|
||||||
|
if (self.ani) {
|
||||||
inlineStyle(self.ele, self.rate < 0 ? self.fromEffect : self.toEffect);
|
inlineStyle(self.ele, self.rate < 0 ? self.fromEffect : self.toEffect);
|
||||||
|
|
||||||
self.ani = null;
|
self.ani = self.ani.onfinish = null;
|
||||||
|
|
||||||
done && done();
|
done && done();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,14 +65,15 @@ export class RippleActivator extends Activator {
|
|||||||
upAction(forceFadeOut) {
|
upAction(forceFadeOut) {
|
||||||
this.deactivate();
|
this.deactivate();
|
||||||
|
|
||||||
let ripple;
|
let rippleId, ripple;
|
||||||
for (let rippleId in this.ripples) {
|
for (rippleId in this.ripples) {
|
||||||
ripple = this.ripples[rippleId];
|
ripple = this.ripples[rippleId];
|
||||||
|
|
||||||
if (!ripple.fade || forceFadeOut) {
|
if (!ripple.fade || forceFadeOut) {
|
||||||
// ripple has not been let up yet
|
// ripple has not been let up yet
|
||||||
|
clearTimeout(ripple.fadeStart);
|
||||||
|
ripple.fadeStart = setTimeout(() => {
|
||||||
// speed up the rate if the animation is still going
|
// speed up the rate if the animation is still going
|
||||||
setTimeout(() => {
|
|
||||||
ripple.expand && ripple.expand.playbackRate(EXPAND_OUT_PLAYBACK_RATE);
|
ripple.expand && ripple.expand.playbackRate(EXPAND_OUT_PLAYBACK_RATE);
|
||||||
ripple.fade = new Animation(ripple.ele);
|
ripple.fade = new Animation(ripple.ele);
|
||||||
ripple.fade
|
ripple.fade
|
||||||
@ -87,7 +88,7 @@ export class RippleActivator extends Activator {
|
|||||||
})
|
})
|
||||||
.play();
|
.play();
|
||||||
|
|
||||||
}, 16);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,15 +96,15 @@ export class RippleActivator extends Activator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
next(forceComplete) {
|
next(forceComplete) {
|
||||||
let ripple, rippleEle;
|
let rippleId, ripple;
|
||||||
for (let rippleId in this.ripples) {
|
for (rippleId in this.ripples) {
|
||||||
ripple = this.ripples[rippleId];
|
ripple = this.ripples[rippleId];
|
||||||
|
|
||||||
if ((ripple.expanded && ripple.faded && ripple.ele) ||
|
if ((ripple.expanded && ripple.faded && ripple.ele) || forceComplete) {
|
||||||
forceComplete || parseInt(rippleId) + 5000 < Date.now()) {
|
|
||||||
// finished expanding and the user has lifted the pointer
|
// finished expanding and the user has lifted the pointer
|
||||||
|
ripple.remove = true;
|
||||||
raf(() => {
|
raf(() => {
|
||||||
this.remove(rippleId);
|
this.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,9 +115,11 @@ export class RippleActivator extends Activator {
|
|||||||
this.next(true);
|
this.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(rippleId) {
|
remove() {
|
||||||
let ripple = this.ripples[rippleId];
|
let rippleId, ripple;
|
||||||
if (ripple) {
|
for (rippleId in this.ripples) {
|
||||||
|
ripple = this.ripples[rippleId];
|
||||||
|
if (ripple.remove || parseInt(rippleId, 10) + 4000 < Date.now()) {
|
||||||
ripple.expand && ripple.expand.dispose();
|
ripple.expand && ripple.expand.dispose();
|
||||||
ripple.fade && ripple.fade.dispose();
|
ripple.fade && ripple.fade.dispose();
|
||||||
removeElement(ripple.ele);
|
removeElement(ripple.ele);
|
||||||
@ -124,6 +127,7 @@ export class RippleActivator extends Activator {
|
|||||||
delete this.ripples[rippleId];
|
delete this.ripples[rippleId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ let lastActivated = 0;
|
|||||||
let disableNativeClickTime = 0;
|
let disableNativeClickTime = 0;
|
||||||
let disableNativeClickLimit = 1000;
|
let disableNativeClickLimit = 1000;
|
||||||
let activator = null;
|
let activator = null;
|
||||||
let isEnabled = false;
|
let isTapPolyfill = false;
|
||||||
let app = null;
|
let app = null;
|
||||||
let config = null;
|
let config = null;
|
||||||
let win = null;
|
let win = null;
|
||||||
@ -24,13 +24,15 @@ export function initTapClick(windowInstance, documentInstance, appInstance, conf
|
|||||||
config = configInstance;
|
config = configInstance;
|
||||||
|
|
||||||
activator = (config.get('mdRipple') ? new RippleActivator(app, config) : new Activator(app, config));
|
activator = (config.get('mdRipple') ? new RippleActivator(app, config) : new Activator(app, config));
|
||||||
isEnabled = (config.get('tapPolyfill') !== false);
|
isTapPolyfill = (config.get('tapPolyfill') === true);
|
||||||
|
|
||||||
addListener('click', click, true);
|
addListener('click', click, true);
|
||||||
|
|
||||||
|
if (isTapPolyfill) {
|
||||||
addListener('touchstart', touchStart);
|
addListener('touchstart', touchStart);
|
||||||
addListener('touchend', touchEnd);
|
addListener('touchend', touchEnd);
|
||||||
addListener('touchcancel', touchCancel);
|
addListener('touchcancel', touchCancel);
|
||||||
|
}
|
||||||
|
|
||||||
addListener('mousedown', mouseDown, true);
|
addListener('mousedown', mouseDown, true);
|
||||||
addListener('mouseup', mouseUp, true);
|
addListener('mouseup', mouseUp, true);
|
||||||
@ -45,7 +47,7 @@ function touchStart(ev) {
|
|||||||
function touchEnd(ev) {
|
function touchEnd(ev) {
|
||||||
touchAction();
|
touchAction();
|
||||||
|
|
||||||
if (isEnabled && startCoord && app.isEnabled()) {
|
if (startCoord && app.isEnabled()) {
|
||||||
let endCoord = pointerCoord(ev);
|
let endCoord = pointerCoord(ev);
|
||||||
|
|
||||||
if (!hasPointerMoved(pointerTolerance, startCoord, endCoord)) {
|
if (!hasPointerMoved(pointerTolerance, startCoord, endCoord)) {
|
||||||
@ -111,8 +113,8 @@ function pointerStart(ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function pointerEnd(ev) {
|
function pointerEnd(ev) {
|
||||||
activator.upAction();
|
|
||||||
moveListeners(false);
|
moveListeners(false);
|
||||||
|
activator.upAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
function pointerMove(ev) {
|
function pointerMove(ev) {
|
||||||
@ -131,16 +133,22 @@ function pointerCancel(ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function moveListeners(shouldAdd) {
|
function moveListeners(shouldAdd) {
|
||||||
|
if (isTapPolyfill) {
|
||||||
removeListener('touchmove', pointerMove);
|
removeListener('touchmove', pointerMove);
|
||||||
|
}
|
||||||
removeListener('mousemove', pointerMove);
|
removeListener('mousemove', pointerMove);
|
||||||
if (shouldAdd) {
|
if (shouldAdd) {
|
||||||
|
if (isTapPolyfill) {
|
||||||
addListener('touchmove', pointerMove);
|
addListener('touchmove', pointerMove);
|
||||||
|
}
|
||||||
addListener('mousemove', pointerMove);
|
addListener('mousemove', pointerMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDisableNativeClick() {
|
function setDisableNativeClick() {
|
||||||
|
if (isTapPolyfill) {
|
||||||
disableNativeClickTime = Date.now() + disableNativeClickLimit;
|
disableNativeClickTime = Date.now() + disableNativeClickLimit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDisabledNativeClick() {
|
function isDisabledNativeClick() {
|
||||||
@ -161,6 +169,8 @@ function click(ev) {
|
|||||||
console.debug('click prevent', preventReason);
|
console.debug('click prevent', preventReason);
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
} else {
|
||||||
|
activator.upAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,10 +74,12 @@ Platform.register({
|
|||||||
scrollAssist: function(p) {
|
scrollAssist: function(p) {
|
||||||
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
||||||
},
|
},
|
||||||
|
tapPolyfill: function(p) {
|
||||||
|
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
||||||
|
},
|
||||||
keyboardHeight: 290,
|
keyboardHeight: 290,
|
||||||
hoverCSS: false,
|
hoverCSS: false,
|
||||||
swipeBackEnabled: function(p) {
|
swipeBackEnabled: function(p) {
|
||||||
return true; // TODO: remove me! Force it to always work for iOS mode for now
|
|
||||||
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
||||||
},
|
},
|
||||||
swipeBackThreshold: 40,
|
swipeBackThreshold: 40,
|
||||||
|
Reference in New Issue
Block a user