1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-03 01:18:43 +02:00

add animation of percent text when in expanded view

This commit is contained in:
sveisvei 2016-12-17 13:53:50 +01:00
parent 138279d415
commit efcfcfa347
3 changed files with 73 additions and 8 deletions

View File

@ -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;
}
}

View File

@ -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}%</text>
>{this.state.percentageText}%</text>
</svg>);
}
}
@ -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,
};

View File

@ -36,7 +36,7 @@ const MetricTab = ({ metrics, featureToggle, toggleFeature }) => {
<Icon style={{ width: '100px', height: '100px', fontSize: '100px', color: '#ccc' }}
name="report problem" title="No metrics avaiable" /> :
<div>
<Progress strokeWidth={10} percentage={lastMinutePercent} width="50" />
<Progress animatePercentageText strokeWidth={10} percentage={lastMinutePercent} width="50" />
</div>
}
<p><strong>Last minute</strong><br /> Yes {lastMinute.yes}, No: {lastMinute.no}</p>