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

Unified Diff: ui/views/controls/throbber.cc

Issue 1098853005: material throbber, take 2 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: revert namespace change Created 5 years, 8 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 | « ui/views/controls/throbber.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/throbber.cc
diff --git a/ui/views/controls/throbber.cc b/ui/views/controls/throbber.cc
index 7b513c7d404461a2c8001f61f244b7d6843aba21..b2a26fccc162584649cbaf0681980b0ed9746997 100644
--- a/ui/views/controls/throbber.cc
+++ b/ui/views/controls/throbber.cc
@@ -5,6 +5,7 @@
#include "ui/views/controls/throbber.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/animation/tween.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
@@ -168,14 +169,52 @@ void MaterialThrobber::OnPaint(gfx::Canvas* canvas) {
return;
}
- gfx::Rect bounds = GetContentsBounds();
- // Inset by half the stroke width to make sure the whole arc is inside
- // the visible rect.
- SkScalar stroke_width = SkIntToScalar(bounds.width()) / 10.0;
- gfx::Rect oval = bounds;
- int inset = SkScalarCeilToInt(stroke_width / 2.0);
- oval.Inset(inset, inset);
+ PaintSpinning(canvas);
+}
+
+void MaterialThrobber::PaintSpinning(gfx::Canvas* canvas) {
+ base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time();
+
+ // This is a Skia port of the MD spinner SVG. The |start_angle| rotation
+ // here corresponds to the 'rotate' animation.
+ base::TimeDelta rotation_time = base::TimeDelta::FromMilliseconds(1568);
+ int64_t start_angle = 270 + 360 * elapsed_time / rotation_time;
+
+ // The sweep angle ranges from -|arc_size| to |arc_size| over 1333ms. CSS
+ // animation timing functions apply in between key frames, so we have to
+ // break up the |arc_time| into two keyframes (-arc_size to 0, then 0 to
+ // arc_size).
+ int64_t arc_size = 270;
+ base::TimeDelta arc_time = base::TimeDelta::FromMilliseconds(666);
+ double arc_size_progress = static_cast<double>(elapsed_time.InMicroseconds() %
+ arc_time.InMicroseconds()) /
+ arc_time.InMicroseconds();
+ // This tween is equivalent to cubic-bezier(0.4, 0.0, 0.2, 1).
+ double sweep =
+ arc_size * gfx::Tween::CalculateValue(gfx::Tween::FAST_OUT_SLOW_IN,
+ arc_size_progress);
+ int64_t sweep_keyframe = (elapsed_time / arc_time) % 2;
+ if (sweep_keyframe == 0)
+ sweep -= arc_size;
+
+ // This part makes sure the sweep is at least 5 degrees long. Roughly
+ // equivalent to the "magic constants" in SVG's fillunfill animation.
+ const double min_sweep_length = 5.0;
+ if (sweep >= 0.0 && sweep < min_sweep_length) {
+ start_angle -= (min_sweep_length - sweep);
+ sweep = min_sweep_length;
+ } else if (sweep <= 0.0 && sweep > -min_sweep_length) {
+ start_angle += (-min_sweep_length - sweep);
+ sweep = -min_sweep_length;
+ }
+
+ // To keep the sweep smooth, we have an additional rotation after each
+ // |arc_time| period has elapsed. See SVG's 'rot' animation.
+ int64_t rot_keyframe = (elapsed_time / (arc_time * 2)) % 4;
+ PaintArc(canvas, start_angle + rot_keyframe * arc_size, sweep);
+}
+void MaterialThrobber::PaintWaiting(gfx::Canvas* canvas) {
// Calculate start and end points. The angles are counter-clockwise because
// the throbber spins counter-clockwise. The finish angle starts at 12 o'clock
// (90 degrees) and rotates steadily. The start angle trails 180 degrees
@@ -186,10 +225,23 @@ void MaterialThrobber::OnPaint(gfx::Canvas* canvas) {
int64_t finish_angle = twelve_oclock + 360 * elapsed_time / revolution_time;
int64_t start_angle = std::max(finish_angle - 180, twelve_oclock);
- SkPath path;
// Negate the angles to convert to the clockwise numbers Skia expects.
- path.arcTo(gfx::RectToSkRect(oval), -start_angle,
- -(finish_angle - start_angle), true);
+ PaintArc(canvas, -start_angle, -(finish_angle - start_angle));
+}
+
+void MaterialThrobber::PaintArc(gfx::Canvas* canvas,
+ SkScalar start_angle,
+ SkScalar sweep) {
+ gfx::Rect bounds = GetContentsBounds();
+ // Inset by half the stroke width to make sure the whole arc is inside
+ // the visible rect.
+ SkScalar stroke_width = SkIntToScalar(bounds.width()) / 10.0;
+ gfx::Rect oval = bounds;
+ int inset = SkScalarCeilToInt(stroke_width / 2.0);
+ oval.Inset(inset, inset);
+
+ SkPath path;
+ path.arcTo(gfx::RectToSkRect(oval), start_angle, sweep, true);
SkPaint paint;
// TODO(estade): find a place for this color.
« no previous file with comments | « ui/views/controls/throbber.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698