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

Unified Diff: chrome/browser/resources/file_manager/js/photo/mosaic_mode.js

Issue 12208042: Smooth scrolling effect to mosaic view. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 7 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
diff --git a/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js b/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
index a1b0be122b49833d591b5bf6e4e26b8168963060..448c2eea285e98b4077b61bb2b11f8dc3f277c68 100644
--- a/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
+++ b/chrome/browser/resources/file_manager/js/photo/mosaic_mode.js
@@ -89,6 +89,12 @@ Mosaic.prototype.__proto__ = HTMLDivElement.prototype;
Mosaic.LAYOUT_DELAY = 200;
/**
+ * Smooth scroll animation duration when scrolling using keyboard or
+ * clicking on a partly visible tile. In ms.
+ */
+Mosaic.ANIMATED_SCROLL_DURATION = 500;
+
+/**
* Decorate a Mosaic instance.
*
* @param {Mosaic} self Self pointer.
@@ -170,6 +176,66 @@ Mosaic.prototype.initListeners_ = function() {
};
/**
+ * Smoothly scrolls the container to the specified position using
+ * f(x) = sqrt(x) speed function normalized to animation duration.
+ * @param {number} targetPosition Horizontal scroll position in pixels.
+ */
+Mosaic.prototype.animatedScrollTo = function(targetPosition) {
+ if (this.scrollAnimation_) {
+ webkitCancelAnimationFrame(this.scrollAnimation_);
+ this.scrollAnimation_ = null;
+ }
+
+ // Mouse move events are fired without touching the mouse because of scrolling
+ // the container. Therefore, these events have to be suppressed.
+ this.suppressHovering_ = true;
+
+ // Calculates integral area from t1 to t2 of f(x) = sqrt(x) dx.
+ var integral = function(t1, t2) {
+ return 2.0 / 3.0 * Math.pow(t2, 3.0 / 2.0) -
+ 2.0 / 3.0 * Math.pow(t1, 3.0 / 2.0);
+ };
+
+ var delta = targetPosition - this.scrollLeft;
+ var factor = delta / integral(0, Mosaic.ANIMATED_SCROLL_DURATION);
+ var startTime = Date.now();
+ var lastPosition = 0;
+ var scrollOffset = this.scrollLeft;
+
+ var animationFrame = function() {
+ var position = Date.now() - startTime;
+ var step = factor *
+ integral(Math.max(0, Mosaic.ANIMATED_SCROLL_DURATION - position),
+ Math.max(0, Mosaic.ANIMATED_SCROLL_DURATION - lastPosition));
+ scrollOffset += step;
+
+ var oldScrollLeft = this.scrollLeft;
+ var newScrollLeft = Math.round(scrollOffset);
+
+ if (oldScrollLeft != newScrollLeft)
+ this.scrollLeft = newScrollLeft;
+
+ if (step == 0 || this.scrollLeft != newScrollLeft) {
+ this.scrollAnimation_ = null;
+ // Release the hovering lock after a safe delay to avoid hovering
+ // a tile because of altering |this.scrollLeft|.
+ setTimeout(function() {
+ if (!this.scrollAnimation_)
+ this.suppressHovering_ = false;
+ }.bind(this), 100);
+ } else {
+ // Continue the animation.
+ this.scrollAnimation_ = requestAnimationFrame(animationFrame);
+ }
+
+ lastPosition = position;
+ }.bind(this);
+
+ // Start the animation.
+ this.scrollAnimation_ = requestAnimationFrame(animationFrame);
+};
+
+/**
* @return {Mosaic.Tile} Selected tile or undefined if no selection.
*/
Mosaic.prototype.getSelectedTile = function() {
@@ -312,7 +378,8 @@ Mosaic.prototype.onResize_ = function() {
*/
Mosaic.prototype.onMouseEvent_ = function(event) {
// Navigating with mouse, enable hover state.
- this.classList.add('hover-visible');
+ if (!this.suppressHovering_)
+ this.classList.add('hover-visible');
if (event.type == 'mousemove')
return;
@@ -569,6 +636,12 @@ Mosaic.Layout.PADDING_BOTTOM = 50;
Mosaic.Layout.SPACING = 10;
/**
+ * Margin for scrolling using keyboard. Distance between a selected tile
+ * and window border.
+ */
+Mosaic.Layout.SCROLL_MARGIN = 30;
+
+/**
* Layout mode: commit to DOM immediately.
*/
Mosaic.Layout.MODE_FINAL = 'final';
@@ -1603,7 +1676,7 @@ Mosaic.Tile.prototype.layout = function(left, top, width, height) {
this.wrapper_ = util.createChild(border, 'img-wrapper');
}
if (this.hasAttribute('selected'))
- this.scrollIntoView();
+ this.scrollIntoView(false);
this.thumbnailLoader_.attachImage(this.wrapper_,
ThumbnailLoader.FillMode.FILL);
@@ -1611,18 +1684,29 @@ Mosaic.Tile.prototype.layout = function(left, top, width, height) {
/**
* If the tile is not fully visible scroll the parent to make it fully visible.
+ * @param {boolean} opt_animated True, if scroll should be animated,
+ * default: true.
*/
-Mosaic.Tile.prototype.scrollIntoView = function() {
+Mosaic.Tile.prototype.scrollIntoView = function(opt_animated) {
if (this.left_ == null) // Not laid out.
return;
- if (this.left_ < this.container_.scrollLeft) {
- this.container_.scrollLeft = this.left_;
+ var targetPosition;
+ var tileLeft = this.left_ - Mosaic.Layout.SCROLL_MARGIN;
+ if (tileLeft < this.container_.scrollLeft) {
+ targetPosition = tileLeft;
} else {
- var tileRight = this.left_ + this.width_;
+ var tileRight = this.left_ + this.width_ + Mosaic.Layout.SCROLL_MARGIN;
var scrollRight = this.container_.scrollLeft + this.container_.clientWidth;
if (tileRight > scrollRight)
- this.container_.scrollLeft = tileRight - this.container_.clientWidth;
+ targetPosition = tileRight - this.container_.clientWidth;
+ }
+
+ if (targetPosition) {
+ if (opt_animated === false)
+ this.container_.scrollLeft = targetPosition;
+ else
+ this.container_.animatedScrollTo(targetPosition);
}
};
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698