如何在React Native中制作一个圆形滑块?

12

我想添加一个类似于范围的组件,但是它实际上是圆形的,而我不知道如何做到这一点。请问你能给我提供一些帮助吗?

以下是我想要的示例:

Circle range

2个回答

33

最近我一直在使用react-native-svg,我认为它非常棒 - SVG和React是天堂般的完美匹配,非常适合创建自定义UI,无需使用本地绘图代码。

这里有一个小的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上,这里

仅仅是一个快速的原型设计,以便让您了解它的样子(两个CircularSlider实例,绝对定位使它们具有相同的中心点):

enter image description here


非常感谢,为我节省了很多时间。 - KD.
1
@KD 请查看这个在Github上非常好的实现 https://github.com/bgryszko/react-native-circular-slider - Stevie
做得好!你怎么编辑这段代码使滑块从顶部开始而不是底部? - Ben Forsrup

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接