Переместить курсор по дуге круга Reaction-native-SVG

Привет, я пытаюсь построить диапазон ввода, который не является действительно круглым, но дуга окружности, как на рисунке ниже.

диапазон ввода

Вот как мне удалось получить этот результат:

import React, { Component } from 'react';
import { PanResponder, View, Dimensions } from 'react-native';
import Svg, { Path, Circle, G, Text, Defs, LinearGradient, Stop } from 'react-native-svg';

import { defaultProps } from './propTypes';

export default class CircleSlider extends Component {
  constructor(props){
    super(props);
    console.log(props.value)
    this.state = {
      angle: props.value,
      cx: 232 / 2,
      cy: 208 / 2,
      r: this.props.dialRadius,
    };
  }

  componentWillMount() {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (e, gs) => true,
      onStartShouldSetPanResponderCapture: (e, gs) => true,
      onMoveShouldSetPanResponder: (e, gs) => true,
      onMoveShouldSetPanResponderCapture: (e, gs) => true,
      onPanResponderMove: (e, gs) => {
        const xOrigin = this.props.xCenter - (this.props.dialRadius + this.props.btnRadius);
        const yOrigin = this.props.yCenter - (this.props.dialRadius + this.props.btnRadius);
        const a = this.cartesianToPolar(gs.moveX - xOrigin, gs.moveY - yOrigin);
        this.setState({ angle: a });
      }
    });
  }

  cartesianToPolar(x, y) {
    const { dialRadius, btnRadius } = this.props;
    const hC = dialRadius + btnRadius;

    if (x === 0) {
      return y > hC ? 0 : 180;
    } else if (y === 0) {
      return x > hC ? 90 : 270;
    } else {
      return (Math.round((Math.atan((y - hC) / (x - hC))) * 180 / Math.PI) + (x > hC ? 90 : 270));
    }
  }

   polarToCartesian(centerX, centerY, radius, angleInDegrees) {
    var angleInRadians = (angleInDegrees-224) * Math.PI / 180.0;
  
    return {
      x: centerX + (radius * Math.cos(angleInRadians)),
      y: centerY + (radius * Math.sin(angleInRadians))
    };
  }
  
  describeArc(x, y, radius, startAngle, endAngle){
  
      var start = this.polarToCartesian(x, y, radius, endAngle);
      var end = this.polarToCartesian(x, y, radius, startAngle);
  
      var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
  
      var d = [
          "M", start.x, start.y, 
          "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y + verticalScaleToAdd
      ].join(" ");
  
      return d;       
  }
  
  render() {
    const { dialWidth, dialRadius, btnRadius, xCenter, yCenter } = this.props;
    const bR = btnRadius;
    const endCoord = this.polarToCartesian(xCenter, yCenter, dialRadius, this.state.angle);
    console.log(this.state.angle)
    return (
      <Svg
        ref="circleslider"
        width="100%"
        height="100%"
      >
        <Path
          stroke="blue"
          strokeWidth={dialWidth}
          fill='none'
          d={this.describeArc(xCenter, yCenter, dialRadius, 0, 270)}
          strokeLinecap="round"
        />

        <G
          x={(endCoord.x - bR).toString()}
          y={(endCoord.y - bR) - dialWidth).toString()}
        >
          <Circle
            r={bR.toString()}
            cx={bR.toString()}
            cy={bR.toString()}
            fill={"black"}
            {...this._panResponder.panHandlers}
          />
          <Text
            x={bR.toString()}
            y={(bR-(this.props.textSize/2)).toString()}
            fontSize={this.props.textSize}
            fill={this.props.textColor}
            textAnchor="middle"
          >
            {this.props.onValueChange(this.state.angle)+''}
          </Text>
        </G>
      </Svg>
    )
  }
}

CircleSlider.defaultProps = defaultProps;

Моя текущая проблема заключается в том, что курсор не очень хорошо следует позиции перемещения при перетаскивании, более того, когда я перетаскиваю его наверх, он плохо центрируется с обводкой. Я думаю, что проблема исходит от cartesianToPolar функция.

0 ответов

Другие вопросы по тегам