Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(455)

Unified Diff: chrome/browser/resources/settings/settings_page/settings_section.js

Issue 2230123002: MD Settings: fix collapse animation once and for all (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@Overscroll2
Patch Set: for review Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/settings/settings_page/settings_section.js
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.js b/chrome/browser/resources/settings/settings_page/settings_section.js
index e0e3afd11a6021b48301e9320e1f14bb1459b0fd..7833f39ba8b31db0bb47bbe0c20c88c58ed6ad2b 100644
--- a/chrome/browser/resources/settings/settings_page/settings_section.js
+++ b/chrome/browser/resources/settings/settings_page/settings_section.js
@@ -16,10 +16,6 @@
* </settings-section>
*/
-// Fast out, slow in.
-var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)';
-var EXPAND_DURATION = 350;
-
var SettingsSectionElement = Polymer({
is: 'settings-section',
@@ -43,6 +39,18 @@ var SettingsSectionElement = Polymer({
value: false,
reflectToAttribute: true,
},
+
+ /**
+ * Original height of the collapsed section, used as the target height when
+ * collapsing after being expanded.
+ * TODO(michaelpg): Get the height dynamically when collapsing using the
+ * card's main page.
+ * @private
+ */
+ collapsedHeight_: {
+ type: Number,
+ value: NaN,
+ },
},
/**
@@ -61,18 +69,9 @@ var SettingsSectionElement = Polymer({
// If the section is not displayed yet (e.g., navigated directly to a
// sub-page), cardHeight and cardWidth are 0, so do not set the height or
// width explicitly.
- // TODO(michaelpg): Improve this logic when refactoring
- // settings-animated-pages.
if (cardHeight && cardWidth) {
- // TODO(michaelpg): Temporary hack to store the height the section
- // should collapse to when it closes.
- card.origHeight_ = cardHeight;
-
card.style.height = cardHeight + 'px';
card.style.width = cardWidth + 'px';
- } else {
- // Set an invalid value so we don't try to use it later.
- card.origHeight_ = NaN;
}
// Place the section's card at its current position but removed from the
@@ -96,138 +95,158 @@ var SettingsSectionElement = Polymer({
* already expanded or transitioning.
*/
canAnimateExpand: function() {
- return !this.classList.contains('expanded');
+ return !this.classList.contains('expanding') &&
+ !this.classList.contains('expanded') && this.$.card.clientHeight > 0;
},
/**
* Animates the section expanding to fill the container. The section is fixed
- * in the viewport during the animation. The section adds the "expanding"
- * class while the animation plays.
+ * in the viewport during the animation, making it safe to adjust the rest of
+ * the DOM after calling this. The section adds the "expanding" class while
+ * the animation plays and "expanded" after it finishes.
*
* @param {!HTMLElement} container The scrolling container to fill.
- * @return {?settings.animation.Animation} Animation played, if any.
+ * @return {!settings.animation.Animation}
*/
animateExpand: function(container) {
- var card = this.$.card;
-
- // The card should start at the top of the page.
- var targetTop = container.getBoundingClientRect().top;
+ // Set the section's height so its card can be removed from the flow
+ // without affecting the surrounding sections during the animation.
+ this.collapsedHeight_ = this.clientHeight;
+ this.style.height = this.collapsedHeight_ + 'px';
this.classList.add('expanding');
- // Nothing to animate.
- if (!card.style.top || !card.style.height)
- return null;
-
- // Expand the card, using minHeight. (The card must span the container's
- // client height, so it must be at least 100% in case the card is too short.
- // If the card is already taller than the container's client height, we
- // don't want to shrink the card to 100% or the content will overflow, so
- // we can't use height, and animating height wouldn't look right anyway.)
- var keyframes = [{
- top: card.style.top,
- minHeight: card.style.height,
- easing: EASING_FUNCTION,
- }, {
- top: targetTop + 'px',
- minHeight: 'calc(100% - ' + targetTop + 'px)',
- }];
- var options = /** @type {!KeyframeEffectOptions} */({
- duration: EXPAND_DURATION
- });
- // TODO(michaelpg): Change elevation of sections.
- return new settings.animation.Animation(card, keyframes, options);
- },
+ // Start the card in place, at its distance from the container's padding.
+ var startTop = this.$.card.getBoundingClientRect().top + 'px';
+ var startHeight = this.$.card.clientHeight + 'px';
- /**
- * Cleans up after animateExpand().
- * @param {boolean} finished Whether the animation finished successfully.
- */
- cleanUpAnimateExpand: function(finished) {
- if (finished) {
+ // Target position is the container's top edge in the viewport.
+ var containerTop = container.getBoundingClientRect().top;
+ var endTop = containerTop + 'px';
+ // The card should stretch from the bottom of the toolbar to the bottom of
+ // the page. calc(100% - top) lets the card resize if the window resizes.
+ var endHeight = 'calc(100% - ' + containerTop + 'px)';
+
+ var animation =
+ this.animateCard_('fixed', startTop, endTop, startHeight, endHeight);
+ animation.finished.then(function() {
this.classList.add('expanded');
- this.$.card.style.top = '';
- this.$.header.hidden = true;
+ }.bind(this), function() {}).then(function() {
+ // Unset these changes whether the animation finished or canceled.
+ this.classList.remove('expanding');
this.style.height = '';
- }
-
- this.classList.remove('expanding');
- this.$.card.style.height = '';
- this.$.card.style.width = '';
+ }.bind(this));
+ return animation;
},
/** @return {boolean} True if the section is currently expanded. */
canAnimateCollapse: function() {
- return this.classList.contains('expanded');
+ return this.classList.contains('expanded') && this.clientHeight > 0 &&
+ !Number.isNaN(this.collapsedHeight_);
+ },
+
+ /**
+ * Prepares for the animation before the other sections become visible.
+ * Call before animateCollapse().
+ * @param {!HTMLElement} container
+ */
+ setUpAnimateCollapse: function(container) {
+ // Prepare the dimensions and set position: fixed.
+ this.$.card.style.width = this.$.card.clientWidth + 'px';
+ this.$.card.style.height = this.$.card.clientHeight + 'px';
+ this.$.card.style.top = container.getBoundingClientRect().top + 'px';
+ this.$.card.style.position = 'fixed';
+
+ // The section can now collapse back into its original height the page so
+ // the other sections appear in the right places.
+ this.classList.remove('expanded');
+ this.classList.add('collapsing');
+ this.style.height = this.collapsedHeight_ + 'px';
},
/**
* Collapses an expanded section's card back into position in the main page.
- * Adds the "expanding" class during the animation.
+ * Call after calling animateCollapse(), unhiding other content and scrolling.
* @param {!HTMLElement} container The scrolling container the card fills.
- * @param {number} prevScrollTop scrollTop of the container before this
- * section expanded.
- * @return {?settings.animation.Animation} Animation played, if any.
+ * @return {!settings.animation.Animation}
*/
- animateCollapse: function(container, prevScrollTop) {
- this.$.header.hidden = false;
+ animateCollapse: function(container) {
+ // Make the card position: absolute, so scrolling is less of a crapshoot.
+ // First find the current distance between this section and the card using
+ // fixed coordinates; the absolute distance will be the same.
+ var fixedCardTop = this.$.card.getBoundingClientRect().top;
+ var fixedSectionTop = this.getBoundingClientRect().top;
+ var distance = fixedCardTop - fixedSectionTop;
+
+ // The target position is right below our header.
+ var headerStyle = getComputedStyle(this.$.header);
+ var cardTargetTop = this.$.header.offsetHeight +
+ parseFloat(headerStyle.marginBottom) +
+ parseFloat(headerStyle.marginTop);
- var startingTop = container.getBoundingClientRect().top;
+ // Start the card at its current height and distance from our top.
+ var startTop = distance + 'px';
+ var startHeight = this.$.card.style.height;
- var card = this.$.card;
- var cardHeightStart = card.clientHeight;
- var cardWidthStart = card.clientWidth;
+ // End at the bottom of our header.
+ var endTop = cardTargetTop + 'px';
+ var endHeight = (this.collapsedHeight_ - cardTargetTop) + 'px';
- this.classList.add('collapsing');
- this.classList.remove('expanding', 'expanded');
+ // The card no longer needs position: fixed.
+ this.$.card.style.position = '';
- // If we navigated here directly, we don't know the original height of the
- // section, so we skip the animation.
- // TODO(michaelpg): remove this condition once sliding is implemented.
- if (Number.isNaN(card.origHeight_))
- return null;
-
- // Restore the section to its proper height to make room for the card.
- this.style.height = (this.clientHeight + card.origHeight_) + 'px';
+ // Collapse this section, animate the card into place, and remove its
+ // other properties.
+ var animation =
+ this.animateCard_('absolute', startTop, endTop, startHeight, endHeight);
+ this.$.card.style.width = '';
+ this.$.card.style.height = '';
+ this.$.card.style.top = '';
- // TODO(michaelpg): this should be in MainPageBehavior(), but we need to
- // wait until the full page height is available (setting the section
- // height).
- container.scrollTop = prevScrollTop;
+ animation.finished.then(function() {
+ this.classList.remove('expanded');
+ }.bind(this), function() {}).then(function() {
+ // The card now determines the section's height automatically.
+ this.style.height = '';
+ this.classList.remove('collapsing');
+ }.bind(this));
+ return animation;
+ },
- // The card is unpositioned, so use its position as the ending state,
- // but account for scroll.
- var targetTop = card.getBoundingClientRect().top - container.scrollTop;
+ /**
+ * Helper function to animate the card's position and height.
+ * @param {string} position CSS position property.
+ * @param {string} startTop Initial top value.
+ * @param {string} endTop Target top value.
+ * @param {string} startHeight Initial height value.
+ * @param {string} endHeight Target height value.
+ * @return {!settings.animation.Animation}
+ * @private
+ */
+ animateCard_: function(position, startTop, endTop, startHeight, endHeight) {
+ // Width does not change.
+ var width = this.$.card.clientWidth + 'px';
+
+ var startFrame = {
+ position: position,
+ width: width,
+ top: startTop,
+ height: startHeight,
+ };
+
+ var endFrame = {
+ position: position,
+ width: width,
+ top: endTop,
+ height: endHeight,
+ };
- // Account for the section header.
- var headerStyle = getComputedStyle(this.$.header);
- targetTop += this.$.header.offsetHeight +
- parseInt(headerStyle.marginBottom, 10) +
- parseInt(headerStyle.marginTop, 10);
-
- var keyframes = [{
- top: startingTop + 'px',
- minHeight: cardHeightStart + 'px',
- easing: EASING_FUNCTION,
- }, {
- top: targetTop + 'px',
- minHeight: card.origHeight_ + 'px',
- }];
var options = /** @type {!KeyframeEffectOptions} */({
- duration: EXPAND_DURATION
+ duration: settings.animation.Timing.DURATION,
+ easing: settings.animation.Timing.EASING,
});
- card.style.width = cardWidthStart + 'px';
-
- return new settings.animation.Animation(card, keyframes, options);
- },
-
- /**
- * Cleans up after animateCollapse().
- * @param {boolean} finished Whether the animation finished successfully.
- */
- cleanUpAnimateCollapse: function(finished) {
- if (finished)
- this.$.card.style.width = '';
+ return new settings.animation.Animation(
+ this.$.card, [startFrame, endFrame], options);
},
});

Powered by Google App Engine
This is Rietveld 408576698