如何在react-native中创建一个圆形滑块

时间:2016-07-07 19:29:11

标签: javascript reactjs react-native reactive-programming

我想添加一个类似的范围组件。但其中一个实际上是循环的,我不知道该怎么做。 你能指点我帮忙吗。

我想要的例子:

Circle range

2 个答案:

答案 0 :(得分:24)

我最近一直在和react-native-svg合作,我认为这太棒了 - SVG和React是极客天堂的比赛,非常适合创建自定义用户界面而不需要下拉到原始绘图代码。

这是一个实现上述内容的CircularSlider组件:

import React,{Component} from 'react'
import {PanResponder,View} from 'react-native'
import Svg,{Path,Circle,G,Text} from 'react-native-svg'

class CircularSlider extends Component {
  constructor(props){
    super(props)
    this.handlePanResponderMove = this.handlePanResponderMove.bind(this)
    this.cartesianToPolar = this.cartesianToPolar.bind(this)
    this.polarToCartesian = this.polarToCartesian.bind(this)
    const {width,height} = props
    const smallestSide = (Math.min(width,height))
    this.state = {
      cx: width/2,
      cy: height/2,
      r: (smallestSide/2)*0.85
    }
  }
  componentWillMount = () => {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onMoveShouldSetPanResponder: () => true,
      onPanResponderMove: this.handlePanResponderMove
    })
  }
  polarToCartesian(angle){
    const {cx,cy,r} = this.state
        , a = (angle-270) * Math.PI / 180.0
        , x = cx + (r * Math.cos(a))
        , y = cy + (r * Math.sin(a))
    return {x,y}
  }
  cartesianToPolar(x,y){
    const {cx,cy} = this.state
    return Math.round((Math.atan((y-cy)/(x-cx)))/(Math.PI/180)+((x>cx) ? 270 : 90))
  }
  handlePanResponderMove({nativeEvent:{locationX,locationY}}){
    this.props.onValueChange(this.cartesianToPolar(locationX,locationY))
  }
  render(){
    const {width,height,value,meterColor,textColor,onValueChange} = this.props
        , {cx,cy,r} = this.state
        , startCoord = this.polarToCartesian(0)
        , endCoord = this.polarToCartesian(value)
    return (
      <Svg onLayout={this.onLayout} width={width} height={height}>
        <Circle cx={cx} cy={cy} r={r} stroke='#eee' strokeWidth={0.5} fill='none'/>
        <Path stroke={meterColor} strokeWidth={5} fill='none'
          d={`M${startCoord.x} ${startCoord.y} A ${r} ${r} 0 ${value>180?1:0} 1 ${endCoord.x} ${endCoord.y}`}/>
        <G x={endCoord.x-7.5} y={endCoord.y-7.5}>
          <Circle cx={7.5} cy={7.5} r={10} fill={meterColor} {...this._panResponder.panHandlers}/>
          <Text key={value+''} x={7.5} y={1} fontSize={10} fill={textColor} textAnchor="middle">{value+''}</Text>
        </G>
      </Svg>
    )
  }
}

export default CircularSlider

完整的示例项目代码位于github here

这只是一个快速原型,可以提供你的想法,但这里看起来如何(CircularSlider的两个实例,绝对定位,因此它们具有相同的中心):

enter image description here

答案 1 :(得分:1)

很酷的项目。一定要分享你创造的东西。我认为其他人也会觉得这很有用。不幸的是,我还没有见过它。如果我这样做,我首先要看看jQuery插件是如何做到的。像https://github.com/magicismight/react-native-svg之类的东西可以帮助你绘制形状。希望我能提供更多帮助。祝你好运!