mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-30 05:14:53 +08:00
23
docs/components/ProgressBar.md
Normal file
23
docs/components/ProgressBar.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# ProgressBar
|
||||||
|
|
||||||
|
Display an activity progress bar.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
[...View props](./View.md)
|
||||||
|
|
||||||
|
**color**: string = '#1976D2'
|
||||||
|
|
||||||
|
Color of the progress bar.
|
||||||
|
|
||||||
|
**indeterminate**: bool = true
|
||||||
|
|
||||||
|
Whether the progress bar will show indeterminate progress.
|
||||||
|
|
||||||
|
**progress**: number
|
||||||
|
|
||||||
|
The progress value (between 0 and 1).
|
||||||
|
|
||||||
|
(web) **trackColor**: string = 'transparent'
|
||||||
|
|
||||||
|
Color of the track bar.
|
||||||
96
examples/components/ProgressBar/ProgressBarExample.js
Normal file
96
examples/components/ProgressBar/ProgressBarExample.js
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { ProgressBar, StyleSheet, View } from 'react-native'
|
||||||
|
import React from 'react';
|
||||||
|
import { storiesOf, action } from '@kadira/storybook';
|
||||||
|
import TimerMixin from 'react-timer-mixin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2013-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* The examples provided by Facebook are for non-commercial testing and
|
||||||
|
* evaluation purposes only.
|
||||||
|
*
|
||||||
|
* Facebook reserves all rights not expressly granted.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
var ProgressBarExample = React.createClass({
|
||||||
|
mixins: [TimerMixin],
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
progress: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.updateProgress();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateProgress() {
|
||||||
|
var progress = this.state.progress + 0.01;
|
||||||
|
this.setState({ progress });
|
||||||
|
this.requestAnimationFrame(() => this.updateProgress());
|
||||||
|
},
|
||||||
|
|
||||||
|
getProgress(offset) {
|
||||||
|
var progress = this.state.progress + offset;
|
||||||
|
return Math.sin(progress % Math.PI) % 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<ProgressBar style={styles.progressView} color="purple" progress={this.getProgress(0.2)} />
|
||||||
|
<ProgressBar style={styles.progressView} color="red" progress={this.getProgress(0.4)} />
|
||||||
|
<ProgressBar style={styles.progressView} color="orange" progress={this.getProgress(0.6)} />
|
||||||
|
<ProgressBar style={styles.progressView} color="yellow" progress={this.getProgress(0.8)} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const examples = [{
|
||||||
|
title: 'progress',
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<ProgressBarExample />
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
title: 'indeterminate',
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<ProgressBar indeterminate style={styles.progressView} trackColor='#D1E3F6' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
var styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
minWidth: 200,
|
||||||
|
marginTop: -20,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
progressView: {
|
||||||
|
marginTop: 20,
|
||||||
|
minWidth: 200
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
examples.forEach((example) => {
|
||||||
|
storiesOf('component: ProgressBar', module)
|
||||||
|
.add(example.title, () => example.render())
|
||||||
|
})
|
||||||
20
src/components/ProgressBar/__tests__/index-test.js
Normal file
20
src/components/ProgressBar/__tests__/index-test.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
|
||||||
|
import assert from 'assert';
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import ProgressBar from '..';
|
||||||
|
|
||||||
|
suite('components/ProgressBar', () => {
|
||||||
|
suite('progress', () => {
|
||||||
|
test('value as percentage is set to "aria-valuenow"', () => {
|
||||||
|
const component = shallow(<ProgressBar progress={0.5} />);
|
||||||
|
assert(component.prop('aria-valuenow') === 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('is ignored when "indeterminate" is "true"', () => {
|
||||||
|
const component = shallow(<ProgressBar indeterminate progress={0.5} />);
|
||||||
|
assert(component.prop('aria-valuenow') === null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
119
src/components/ProgressBar/index.js
Normal file
119
src/components/ProgressBar/index.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import Animated from '../../apis/Animated';
|
||||||
|
import applyNativeMethods from '../../modules/applyNativeMethods';
|
||||||
|
import ColorPropType from '../../propTypes/ColorPropType';
|
||||||
|
import StyleSheet from '../../apis/StyleSheet';
|
||||||
|
import View from '../View';
|
||||||
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
|
||||||
|
const indeterminateWidth = '25%';
|
||||||
|
const translateInterpolation = { inputRange: [ 0, 1 ], outputRange: [ '-100%', '400%' ] };
|
||||||
|
|
||||||
|
class ProgressBar extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
...View.propTypes,
|
||||||
|
color: ColorPropType,
|
||||||
|
indeterminate: PropTypes.bool,
|
||||||
|
progress: PropTypes.number,
|
||||||
|
trackColor: ColorPropType
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
color: '#1976D2',
|
||||||
|
indeterminate: false,
|
||||||
|
progress: 0,
|
||||||
|
trackColor: 'transparent'
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
animationScale: new Animated.Value(0),
|
||||||
|
animationTranslate: new Animated.Value(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._manageAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this._manageAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
color,
|
||||||
|
indeterminate,
|
||||||
|
progress,
|
||||||
|
trackColor,
|
||||||
|
style,
|
||||||
|
...other
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const { animationTranslate } = this.state;
|
||||||
|
|
||||||
|
const percentageProgress = indeterminate ? 50 : progress * 100;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View {...other}
|
||||||
|
accessibilityRole='progressbar'
|
||||||
|
aria-valuemax='100'
|
||||||
|
aria-valuemin='0'
|
||||||
|
aria-valuenow={indeterminate ? null : percentageProgress}
|
||||||
|
style={[
|
||||||
|
styles.track,
|
||||||
|
style,
|
||||||
|
{ backgroundColor: trackColor }
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Animated.View style={[
|
||||||
|
styles.progress,
|
||||||
|
{ backgroundColor: color },
|
||||||
|
indeterminate ? {
|
||||||
|
transform: [
|
||||||
|
{ translateX: animationTranslate.interpolate(translateInterpolation) }
|
||||||
|
],
|
||||||
|
width: indeterminateWidth
|
||||||
|
} : {
|
||||||
|
width: `${percentageProgress}%`
|
||||||
|
}
|
||||||
|
]} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_manageAnimation() {
|
||||||
|
const { animationTranslate } = this.state;
|
||||||
|
|
||||||
|
const cycleAnimation = (animation) => {
|
||||||
|
animation.setValue(0);
|
||||||
|
Animated.timing(animation, {
|
||||||
|
duration: 1000,
|
||||||
|
toValue: 1
|
||||||
|
}).start((event) => {
|
||||||
|
if (event.finished) {
|
||||||
|
cycleAnimation(animation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.props.indeterminate) {
|
||||||
|
cycleAnimation(animationTranslate);
|
||||||
|
} else {
|
||||||
|
animationTranslate.stopAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
track: {
|
||||||
|
height: 5,
|
||||||
|
overflow: 'hidden',
|
||||||
|
userSelect: 'none'
|
||||||
|
},
|
||||||
|
progress: {
|
||||||
|
height: '100%'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = applyNativeMethods(ProgressBar);
|
||||||
@@ -25,6 +25,7 @@ import Vibration from './apis/Vibration';
|
|||||||
import ActivityIndicator from './components/ActivityIndicator';
|
import ActivityIndicator from './components/ActivityIndicator';
|
||||||
import Image from './components/Image';
|
import Image from './components/Image';
|
||||||
import ListView from './components/ListView';
|
import ListView from './components/ListView';
|
||||||
|
import ProgressBar from './components/ProgressBar';
|
||||||
import ScrollView from './components/ScrollView';
|
import ScrollView from './components/ScrollView';
|
||||||
import Switch from './components/Switch';
|
import Switch from './components/Switch';
|
||||||
import Text from './components/Text';
|
import Text from './components/Text';
|
||||||
@@ -75,6 +76,7 @@ const ReactNative = {
|
|||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Image,
|
Image,
|
||||||
ListView,
|
ListView,
|
||||||
|
ProgressBar,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
Switch,
|
Switch,
|
||||||
Text,
|
Text,
|
||||||
|
|||||||
Reference in New Issue
Block a user