Skip to content

Commit

Permalink
[MirrorSync] Reimplement performant smooth pie progress
Browse files Browse the repository at this point in the history
Reimplement pie progress smooth transitions using pure CSS
transitions for improved rendering performance.

This CL has been stress tested by running 50 Drive uploads in
parallel and observing its performance impact on the "Performance"
tab of Chrome Dev Tools.

Bug: b:289167014
Test: Manual performance test of 50 files uploading in parallel using Dev Tools' Performance tab
Change-Id: I846497d66311b854271ef925bbdde3ebfb345d38
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4654508
Reviewed-by: Ben Reich <benreich@chromium.org>
Commit-Queue: Ben Reich <benreich@chromium.org>
Auto-Submit: Marcello Salomao <msalomao@google.com>
Cr-Commit-Position: refs/heads/main@{#1182954}
  • Loading branch information
Marcello Salomao authored and Chromium LUCI CQ committed Aug 14, 2023
1 parent 9cc0c5a commit 9b82b82
Showing 1 changed file with 49 additions and 75 deletions.
124 changes: 49 additions & 75 deletions ui/file_manager/file_manager/widgets/xf_pie_progress.ts
Expand Up @@ -6,9 +6,6 @@ import {addCSSPrefixSelector} from '../common/js/dom_utils.js';

import {css, customElement, html, property, svg, XfBase} from './xf_base.js';

const TWO_PI = 2.0 * Math.PI;
const HALF_PI = 0.5 * Math.PI;

/**
* Displays a pie shaped progress indicator.
* Accepts a `progress` property ranging from 0 to 1.
Expand All @@ -22,20 +19,29 @@ export class XfPieProgress extends XfBase {
private center = this.size / 2.0; // Center of the pie circle (both X and Y).
private radius = 5.4; // Radius of the pie circle.

private outlineShape = svg`<circle
class="outline"
cx="${this.center}"
cy="${this.center}"
r="${this.center}"
/>`;
private queuedShape = svg`<circle
private outlineShape = svg`
<circle
class="outline"
cx="${this.center}"
cy="${this.center}"
r="${this.center}"
/>`;
private queuedShape = svg`
<circle
class="queued"
stroke-width="1.6"
cx="${this.center}"
cy="${this.center}"
r="5.6"
fill="none"
stroke-width="1.6"
/>;`;
/>`;
private edgeShape = svg`
<circle
class="edge"
stroke-width="2"
cx="${this.center}"
cy="${this.center}"
r="${this.radius}"
/>`;

static override get styles() {
return getCSS();
Expand All @@ -44,59 +50,29 @@ export class XfPieProgress extends XfBase {
override render() {
const {progress, size, center, radius} = this;

let contents = svg``;

if (progress === 0) {
// Display the queued shape.
contents = this.queuedShape;
} else if (progress >= 0.99) {
// The completed pie is easier to draw.
contents = svg`
<circle
class="edge full"
stroke-width="2"
cx="${center}"
cy="${center}"
r="${radius}"
/>
`;
} else {
// Finishing angle of the pie arc. Notice that the starting angle is
// always -PI/2. I.e., the pie is drawn starting from the top of the
// circle and it advances in a clockwise fashion.
const radians = TWO_PI * progress - HALF_PI;

// Finishing cartesian coordinates of the pie arc. Notice that the
// starting coordinates are always <0, -radius> (the top of the circle).
const x = center + radius * Math.cos(radians);
const y = center + radius * Math.sin(radians);

// Determines which arc fitting the other arguments should be rendered.
// Render the smaller one until we are drawing an arc with an angle
// greater than 180 degrees. More info:
// https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
const largeArcFlag = progress <= 0.5 ? '0' : '1';

contents = svg`<circle
class="edge"
stroke-width="2"
cx="${center}"
cy="${center}"
r="${radius}"
/>
<path
class="pie"
d="
M ${center} ${center}
l 0 ${- radius}
A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x} ${y}
Z"
/>`;
}
const isQueued = progress === 0;

// The progress pie is drawn as an arc with a thick stroke width (as thick
// as the radius of the pie).
const arcRadius = radius * 0.5;
const maxArcLength = 2.0 * Math.PI * arcRadius;
const pie = svg`
<circle class="pie"
stroke-width="${radius}"
stroke-dasharray="${maxArcLength}"
stroke-dashoffset="${maxArcLength * (1 - progress)}"
cx="${center}"
cy="${center}"
r="${arcRadius}"
transform="rotate(-90, ${center}, ${center})"
visibility="${isQueued ? 'hidden' : 'visible'}"
/>`;

const edge = isQueued ? this.queuedShape : this.edgeShape;

return html`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}">
${this.outlineShape} ${contents}
${this.outlineShape} ${pie} ${edge}
</svg>
`;
}
Expand All @@ -110,6 +86,7 @@ function getCSS() {
}
.queued {
fill: none;
stroke: var(--cros-icon-color-secondary);
}
Expand All @@ -118,17 +95,15 @@ function getCSS() {
stroke: var(--cros-icon-color-prominent);
}
.full {
fill: var(--cros-icon-color-prominent);
}
.pie {
fill: var(--cros-icon-color-prominent);
stroke: none;
fill: none;
stroke: var(--cros-icon-color-prominent);
transition: stroke-dashoffset 1s ease-out;
}
.outline {
fill: var(--xf-icon-color-outline, transparent);
stroke: none;
}
`;

Expand All @@ -139,6 +114,7 @@ function getCSS() {
}
.queued {
fill: none;
stroke: currentColor
}
Expand All @@ -147,17 +123,15 @@ function getCSS() {
stroke: var(--cros-sys-progress);
}
.full {
fill: var(--cros-sys-progress);
}
.pie {
fill: var(--cros-sys-progress);
stroke: none;
fill: none;
stroke: var(--cros-sys-progress);
transition: stroke-dashoffset 1s ease-out;
}
.outline {
fill: var(--xf-icon-color-outline, transparent);
stroke: none;
}
`;

Expand Down

0 comments on commit 9b82b82

Please sign in to comment.