Переместить курсор по дуге круга 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
функция.