PERF: Animate request animation frame (#13337)

* PERF: requestanimationframe for better performance on pan events
* PERF: temporarily remove items on animate
This commit is contained in:
Jeff Wong
2021-06-09 04:26:52 -10:00
committed by GitHub
parent 513bfc3a6c
commit f12551afd3
3 changed files with 30 additions and 7 deletions

View File

@@ -87,6 +87,7 @@ const SiteHeaderComponent = MountWidget.extend(
const menuPanels = document.querySelectorAll(".menu-panel"); const menuPanels = document.querySelectorAll(".menu-panel");
const menuOrigin = this._panMenuOrigin; const menuOrigin = this._panMenuOrigin;
menuPanels.forEach((panel) => { menuPanels.forEach((panel) => {
panel.classList.remove("moving");
if (this._shouldMenuClose(event, menuOrigin)) { if (this._shouldMenuClose(event, menuOrigin)) {
this._animateClosing(panel, menuOrigin); this._animateClosing(panel, menuOrigin);
} else { } else {
@@ -129,6 +130,10 @@ const SiteHeaderComponent = MountWidget.extend(
) { ) {
e.originalEvent.preventDefault(); e.originalEvent.preventDefault();
this._isPanning = true; this._isPanning = true;
const panel = document.querySelector(".menu-panel");
if (panel) {
panel.classList.add("moving");
}
} else { } else {
this._isPanning = false; this._isPanning = false;
} }

View File

@@ -10,6 +10,7 @@ export default Mixin.create({
//velocity is pixels per ms //velocity is pixels per ms
_panState: null, _panState: null,
_animationPending: false,
didInsertElement() { didInsertElement() {
this._super(...arguments); this._super(...arguments);
@@ -71,9 +72,7 @@ export default Mixin.create({
//calculate delta x, y, distance from START location //calculate delta x, y, distance from START location
const deltaX = e.clientX - oldState.startLocation.x; const deltaX = e.clientX - oldState.startLocation.x;
const deltaY = e.clientY - oldState.startLocation.y; const deltaY = e.clientY - oldState.startLocation.y;
const distance = Math.round( const distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2))
);
//calculate velocity from previous event center location //calculate velocity from previous event center location
const eventDeltaX = e.clientX - oldState.center.x; const eventDeltaX = e.clientX - oldState.center.x;
@@ -87,7 +86,7 @@ export default Mixin.create({
return { return {
startLocation: oldState.startLocation, startLocation: oldState.startLocation,
center: { x: Math.round(e.clientX), y: Math.round(e.clientY) }, center: { x: e.clientX, y: e.clientY },
velocity, velocity,
velocityX, velocityX,
velocityY, velocityY,
@@ -102,7 +101,7 @@ export default Mixin.create({
_panStart(e) { _panStart(e) {
const newState = { const newState = {
center: { x: Math.round(e.clientX), y: Math.round(e.clientY) }, center: { x: e.clientX, y: e.clientY },
startLocation: { x: e.clientX, y: e.clientY }, startLocation: { x: e.clientX, y: e.clientY },
velocity: 0, velocity: 0,
velocityX: 0, velocityX: 0,
@@ -122,6 +121,7 @@ export default Mixin.create({
this._panStart(e); this._panStart(e);
return; return;
} }
const previousState = this._panState; const previousState = this._panState;
const newState = this._calculateNewPanState(previousState, e); const newState = this._calculateNewPanState(previousState, e);
if (previousState.start && newState.distance < MINIMUM_SWIPE_DISTANCE) { if (previousState.start && newState.distance < MINIMUM_SWIPE_DISTANCE) {
@@ -137,7 +137,17 @@ export default Mixin.create({
) { ) {
this.panEnd(newState); this.panEnd(newState);
} else if (e.type === "pointermove" && "panMove" in this) { } else if (e.type === "pointermove" && "panMove" in this) {
this.panMove(newState); if (this._animationPending) {
return;
}
this._animationPending = true;
window.requestAnimationFrame(() => {
if (!this._animationPending) {
return;
}
this.panMove(newState);
this._animationPending = false;
});
} }
}, },
}); });

View File

@@ -27,12 +27,20 @@
} }
.menu-panel.slide-in { .menu-panel.slide-in {
transform: translate(var(--offset), 0); transform: translateX(var(--offset));
@media (prefers-reduced-motion: no-preference) { @media (prefers-reduced-motion: no-preference) {
&.animate { &.animate {
transition: transform 0.1s linear; transition: transform 0.1s linear;
} }
} }
&.moving,
&.animate {
// PERF: only render first 20 items in a list to allow for smooth
// pan events
li:nth-child(n + 20) {
display: none;
}
}
} }
.user-menu .quick-access-panel.quick-access-profile li:not(.show-all) { .user-menu .quick-access-panel.quick-access-profile li:not(.show-all) {