Skip to content

Commit

Permalink
Merge pull request #4705 from pomerantsev/circular-progress-improvements
Browse files Browse the repository at this point in the history
[CircularProgress] Update component API (breaking change)
  • Loading branch information
chowdream committed Jul 16, 2016
2 parents b57d476 + 4bd8b88 commit f6f001d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 39 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

##### Breaking Changes
- [Badge] Swapped primary and accent colors (#4449)
- [CircularProgress] The API has become more flexible and straightforward. `size` attribute now means the outer diameter in pixels. Line thickness is variable and should be defined via the `thickness` attribute. Default margins are eliminated. If you'd like to upgrade your existing app without changing the actual sizes of your `CircularProgress` components, here are the formulas:
```js
newSize = 59.5 * oldSize;
thickness = 3.5 * oldSize;
margin = (oldSize < 0.71) ?
((50 - 59.5 * oldSize) / 2) :
(5.25 * oldSize);
```

Examples:
```
// Before:
<CircularProgress />
<CircularProgress size={2} />
// After:
<CircularProgress size={59.5} style={{margin: 5.25}} /> // Thickness is 3.5 by default
<CircularProgress size={119} thickness={7} style={{margin: 10.5}} />
```

## 0.15.2
###### _Jul 7, 2016_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,22 @@ export default class CircularProgressExampleDeterminate extends React.Component
render() {
return (
<div>
<CircularProgress mode="determinate" value={this.state.completed} />
<CircularProgress mode="determinate" value={this.state.completed} size={1.5} />
<CircularProgress mode="determinate" value={this.state.completed} size={2} />
<CircularProgress
mode="determinate"
value={this.state.completed}
/>
<CircularProgress
mode="determinate"
value={this.state.completed}
size={60}
thickness={7}
/>
<CircularProgress
mode="determinate"
value={this.state.completed}
size={80}
thickness={5}
/>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import CircularProgress from 'material-ui/CircularProgress';
const CircularProgressExampleSimple = () => (
<div>
<CircularProgress />
<CircularProgress size={1.5} />
<CircularProgress size={2} />
<CircularProgress size={60} thickness={7} />
<CircularProgress size={80} thickness={5} />
</div>
);

Expand Down
69 changes: 35 additions & 34 deletions src/CircularProgress/CircularProgress.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import transitions from '../styles/transitions';

function getRelativeValue(value, min, max) {
const clampedValue = Math.min(Math.max(min, value), max);
const rangeValue = max - min;
const relValue = Math.round(clampedValue / rangeValue * 10000) / 10000;
return relValue * 100;
return clampedValue / (max - min);
}

function getArcLength(fraction, props) {
return fraction * Math.PI * (props.size - props.thickness);
}

function getStyles(props, context) {
Expand All @@ -18,36 +20,27 @@ function getStyles(props, context) {
} = props;

const {baseTheme: {palette}} = context.muiTheme;
const zoom = size * 1.4 ;
const baseSize = 50;
let margin = Math.round( ((50 * zoom) - 50) / 2 );

if (margin < 0) margin = 0;

const styles = {
root: {
position: 'relative',
margin: margin,
display: 'inline-block',
width: baseSize,
height: baseSize,
width: size,
height: size,
},
wrapper: {
width: baseSize,
height: baseSize,
width: size,
height: size,
display: 'inline-block',
transition: transitions.create('transform', '20s', null, 'linear'),
transitionTimingFunction: 'linear',
},
svg: {
height: baseSize,
width: size,
height: size,
position: 'relative',
transform: `scale(${zoom})`,
width: baseSize,
},
path: {
strokeDasharray: '89, 200',
strokeDashoffset: 0,
stroke: props.color || palette.primary1Color,
strokeLinecap: 'round',
transition: transitions.create('all', '1.5s', null, 'ease-in-out'),
Expand All @@ -57,7 +50,7 @@ function getStyles(props, context) {
if (props.mode === 'determinate') {
const relVal = getRelativeValue(value, min, max);
styles.path.transition = transitions.create('all', '0.3s', null, 'linear');
styles.path.strokeDasharray = `${Math.round(relVal * 1.25)}, 200`;
styles.path.strokeDasharray = `${getArcLength(relVal, props)}, ${getArcLength(1, props)}`;
}

return styles;
Expand Down Expand Up @@ -87,13 +80,17 @@ class CircularProgress extends Component {
*/
mode: PropTypes.oneOf(['determinate', 'indeterminate']),
/**
* The size of the progress.
* The diameter of the progress in pixels.
*/
size: PropTypes.number,
/**
* Override the inline-styles of the root element.
*/
style: PropTypes.object,
/**
* Stroke width in pixels.
*/
thickness: PropTypes.number,
/**
* The value of progress, only works in determinate mode.
*/
Expand All @@ -105,7 +102,8 @@ class CircularProgress extends Component {
value: 0,
min: 0,
max: 100,
size: 1,
size: 40,
thickness: 3.5,
};

static contextTypes = {
Expand All @@ -122,23 +120,22 @@ class CircularProgress extends Component {
clearTimeout(this.rotateWrapperTimer);
}

scalePath(path, step) {
scalePath(path, step = 0) {
if (this.props.mode !== 'indeterminate') return;

step = step || 0;
step %= 3;

if (step === 0) {
path.style.strokeDasharray = '1, 200';
path.style.strokeDasharray = `${getArcLength(0, this.props)}, ${getArcLength(1, this.props)}`;
path.style.strokeDashoffset = 0;
path.style.transitionDuration = '0ms';
} else if (step === 1) {
path.style.strokeDasharray = '89, 200';
path.style.strokeDashoffset = -35;
path.style.strokeDasharray = `${getArcLength(0.7, this.props)}, ${getArcLength(1, this.props)}`;
path.style.strokeDashoffset = getArcLength(-0.3, this.props);
path.style.transitionDuration = '750ms';
} else {
path.style.strokeDasharray = '89, 200';
path.style.strokeDashoffset = -124;
path.style.strokeDasharray = `${getArcLength(0.7, this.props)}, ${getArcLength(1, this.props)}`;
path.style.strokeDashoffset = getArcLength(-1, this.props);
path.style.transitionDuration = '850ms';
}

Expand All @@ -164,7 +161,8 @@ class CircularProgress extends Component {
const {
style,
innerStyle,
size, // eslint-disable-line no-unused-vars
size,
thickness,
...other,
} = this.props;

Expand All @@ -174,15 +172,18 @@ class CircularProgress extends Component {
return (
<div {...other} style={prepareStyles(Object.assign(styles.root, style))} >
<div ref="wrapper" style={prepareStyles(Object.assign(styles.wrapper, innerStyle))} >
<svg style={prepareStyles(styles.svg)} >
<svg
viewBox={`0 0 ${size} ${size}`}
style={prepareStyles(styles.svg)}
>
<circle
ref="path"
style={prepareStyles(styles.path)}
cx="25"
cy="25"
r="20"
cx={size / 2}
cy={size / 2}
r={(size - thickness) / 2}
fill="none"
strokeWidth="2.5"
strokeWidth={thickness}
strokeMiterlimit="20"
/>
</svg>
Expand Down

0 comments on commit f6f001d

Please sign in to comment.