emmmm,不多说了,代码贴下面,各位大佬自己参透吧~
import React, { PureComponent } from 'react'
import Svg, { Path, Circle, G } from 'react-native-svg'
import { View, PanResponder } from 'react-native'
let runNumber_change = 0;
export default class Slider extends PureComponent {
static defaultProps = {
min: 0, // 最小值
max: 100, // 最大值
width: 20,
color: '#128BFC',
backgroundColor: '#F5F5F5',
curColor: '#ffffff'
}
constructor(props) {
super(props)
this._panResponder = PanResponder.create({
// 要求成为响应者:
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: this._handlePanResponderGrant,
onPanResponderMove: this._handlePanResponderMove,
onPanResponderTerminationRequest: () => true,
onPanResponderRelease: this._handlePanResponderEnd,
onPanResponderTerminate: this._handlePanResponderEnd,
});
this.state = {
value: props.value || props.min,
svgWidth: 0
}
}
static getDerivedStateFromProps(nextProps, prevState) {
//该方法内禁止访问this
if (nextProps.value !== prevState.value) {
//通过对比nextProps和prevState,返回一个用于更新状态的对象
if (runNumber_change == 0) {
return { value: nextProps.value }
} else {
return prevState
}
}
//不需要更新状态,返回null
return null
}
_handlePanResponderGrant = () => {
/*
* 记录开始滑动时的滑块值,用于后续值的计算
*/
this._moveStartValue = this.getPointValue(this.getEndValue(), this.getStartValue(), this.state.value)
runNumber_change = 1;
};
_handlePanResponderMove = (e, gestureState) => {
const { min, max } = this.props || this.defaultProps
let x = gestureState.dx
let increment = x + this._moveStartValue
increment = (increment - this.props.width / 2) / ((this.getEndValue() - this.getStartValue()) / max)
increment = Math.round(increment)
if (increment >= max) increment = max;
if (increment <= min) increment = min;
this.setState({ value: increment })
this._fireChangeEvent('onChange');
}
_handlePanResponderEnd = (e, gestureState) => {
if (this.props.disabled) {
return;
}
this._fireChangeEvent('onComplete');
runNumber_change = 0;
}
_fireChangeEvent = event => {
if (this.props[event]) {
this.props[event](this.state.value);
}
};
_onLayout = (event) => {
this.setState({ svgWidth: event.nativeEvent.layout.width })
}
getStartValue = () => {
return this.props.width / 2
}
getEndValue = () => {
return this.state.svgWidth - this.props.width / 2;
}
getPointValue = (endValue, start, value) => {
const { max, min } = this.props || this.defaultProps
let PointValue = ((endValue - start) / (max - min) * value) + this.props.width / 2
if (PointValue <= start) {
PointValue = start
}
if (PointValue >= endValue) {
PointValue = endValue
}
return PointValue - this.props.width / 2
}
getCurValue = (pointValue) => {
return pointValue + this.props.width / 2
}
render() {
const {
style,
disabled
} = this.props
const start = this.getStartValue()
const endValue = this.getEndValue()
const pointValue = this.getPointValue(endValue, start, this.state.value)
const curValue = this.getCurValue(pointValue)
const width = this.props.width || this.defaultProps.width
const color = this.props.color || this.defaultProps.color
const backgroundColor = this.props.backgroundColor || this.defaultProps.backgroundColor
const curColor = this.props.curColor || this.defaultProps.curColor
const disabledColor = this.props.disabledColor || this.defaultProps.disabledColor
return (
<View onLayout={this._onLayout} style={[{ position: 'relative' }, style]}>
{
this.state.svgWidth ?
<Svg height={width} width='100%'>
<G fill="none" stroke={backgroundColor}>
<Path strokeLinecap="round" strokeWidth={width} d={`M${start} ${width / 2} l${this.state.svgWidth - this.props.width} 0`} />
</G>
<G fill="none" stroke={disabled ? disabledColor : color}>
<Path strokeLinecap="round" strokeWidth={width} d={`M${start} ${width / 2} l${pointValue} 0`} />
</G>
{
disabled ?
<Circle
cx={curValue}
cy={width / 2}
r={width / 2 - (width / 100 * 10)}
fill={curColor}
stroke={5}
strokeWidth={20}
fillOpacity={1}
strokeOpacity={1} /> :
<Circle
cx={curValue}
cy={width / 2}
r={width / 2 - (width / 100 * 10)}
fill={curColor}
stroke={5}
strokeWidth={20}
fillOpacity={1}
strokeOpacity={1}
{...this._panResponder.panHandlers} />
}
</Svg> : null
}
</View>
)
}
}
大概就是这样咯~ 功能比较简单 或许不会在所有场景都那么好用,原本也就是工作需要特意写的~走过路过的大佬欢迎留下宝贵意见,万分感谢!