diff --git a/frontend/src/component/feature/progress-styles.scss b/frontend/src/component/feature/progress-styles.scss
index c036577277..c3a79c7de9 100644
--- a/frontend/src/component/feature/progress-styles.scss
+++ b/frontend/src/component/feature/progress-styles.scss
@@ -1,7 +1,7 @@
.path {
stroke: #3f51b5;
stroke-linecap: round;
- transition: stroke-dashoffset 5s ease 0s;
+ transition: stroke-dashoffset 11s ease 0s;
}
.trail {
@@ -14,4 +14,4 @@
line-height: 25px;
dominant-baseline: middle;
text-anchor: middle;
-}
\ No newline at end of file
+}
diff --git a/frontend/src/component/feature/progress.jsx b/frontend/src/component/feature/progress.jsx
index 59386daeb3..c5b67fb3fd 100644
--- a/frontend/src/component/feature/progress.jsx
+++ b/frontend/src/component/feature/progress.jsx
@@ -7,13 +7,14 @@ class Progress extends Component {
this.state = {
percentage: props.initialAnimation ? 0 : props.percentage,
+ percentageText: props.initialAnimation ? 0 : props.percentage,
};
}
componentDidMount () {
if (this.props.initialAnimation) {
this.initialTimeout = setTimeout(() => {
- this.requestAnimationFrame = window.requestAnimationFrame(() => {
+ this.rafTimerInit = window.requestAnimationFrame(() => {
this.setState({
percentage: this.props.percentage,
});
@@ -23,16 +24,78 @@ class Progress extends Component {
}
componentWillReceiveProps ({ percentage }) {
- this.setState({ percentage });
+ if (this.state.percentage !== percentage) {
+ const nextState = { percentage };
+ if (this.props.animatePercentageText) {
+ this.animateTo(percentage, this.getTarget(percentage));
+ } else {
+ nextState.percentageText = percentage;
+ }
+ this.setState(nextState);
+ }
}
+ getTarget (target) {
+ const start = this.state.percentageText;
+ const TOTAL_ANIMATION_TIME = 10000;
+ const diff = start > target ? -(start - target) : target - start;
+ const perCycle = TOTAL_ANIMATION_TIME / diff;
+ const cyclesCounter = Math.round(Math.abs(TOTAL_ANIMATION_TIME / perCycle));
+ const perCycleTime = Math.round(Math.abs(perCycle));
+
+ let usedTime = 0;
+ // this initial value could be tweaked more
+ let lastTime = perCycleTime / 4;
+ return {
+ start,
+ target,
+ cyclesCounter,
+ getTimer () {
+ /* Somewhat tweaked values to get a curve on the counting */
+ if (usedTime > (TOTAL_ANIMATION_TIME / 2)) {
+ // if halfway, lets speed up timeouts
+ lastTime *= 0.95;
+ } else {
+ lastTime *= 1.1;
+ }
+ usedTime += lastTime;
+ return lastTime;
+ },
+ increment: diff / cyclesCounter,
+ };
+ }
+
+ animateTo (percentage, targetState) {
+ cancelAnimationFrame(this.rafCounterTimer);
+ clearTimeout(this.nextTimer);
+
+ const current = this.state.percentageText;
+
+ targetState.cyclesCounter --;
+ if (targetState.cyclesCounter <= 0) {
+ this.setState({ percentageText: targetState.target });
+ return;
+ }
+
+ const next = Math.round(current + targetState.increment);
+ this.rafCounterTimer = requestAnimationFrame(() => {
+ this.setState({ percentageText: next });
+ this.nextTimer = setTimeout(() => {
+ this.animateTo(next, targetState);
+ }, targetState.getTimer());
+ });
+ }
+
+
componentWillUnmount () {
clearTimeout(this.initialTimeout);
- window.cancelAnimationFrame(this.requestAnimationFrame);
+ clearTimeout(this.nextTimer);
+ window.cancelAnimationFrame(this.rafTimerInit);
+ window.cancelAnimationFrame(this.rafCounterTimer);
}
render () {
- const { strokeWidth, percentage } = this.props;
+ const { strokeWidth } = this.props;
const radius = (50 - strokeWidth / 2);
const pathDescription = `
M 50,50 m 0,-${radius}
@@ -66,7 +129,7 @@ class Progress extends Component {
className={styles.text}
x={50}
y={50}
- >{percentage}%
+ >{this.state.percentageText}%
);
}
}
@@ -75,11 +138,13 @@ Progress.propTypes = {
percentage: PropTypes.number.isRequired,
strokeWidth: PropTypes.number,
initialAnimation: PropTypes.bool,
+ animatePercentageText: PropTypes.bool,
textForPercentage: PropTypes.func,
};
Progress.defaultProps = {
strokeWidth: 8,
+ animatePercentageText: false,
initialAnimation: false,
};
diff --git a/frontend/src/component/feature/view-edit-container.jsx b/frontend/src/component/feature/view-edit-container.jsx
index 867aa41662..f3d2644374 100644
--- a/frontend/src/component/feature/view-edit-container.jsx
+++ b/frontend/src/component/feature/view-edit-container.jsx
@@ -36,7 +36,7 @@ const MetricTab = ({ metrics, featureToggle, toggleFeature }) => {
Last minute
Yes {lastMinute.yes}, No: {lastMinute.no}