Почему мой вращающийся руль иногда вращается в неправильном направлении?
Я делаю вращающееся колесо управления. Вы можете перетащить его куда угодно, чтобы вращать элемент управления по его центральной точке.
Это не ведет себя правильно. Обычно он работает хорошо, но для некоторой части вращения он начинает вращаться в противоположном направлении в течение короткого периода времени, а затем снова начинает вращаться пальцем. РЕДАКТИРОВАТЬ: После дальнейшего тестирования, я понял, что вам не нужно поворачивать его на 360 градусов, чтобы он вращался в неправильном направлении.
Возможно, не связанная с этим проблема заключается в том, что элемент управления движется медленнее, чем ваш палец. Если решение исходной проблемы не решит эту проблему, я задам отдельный вопрос.
Я опубликовал пример проекта. Если вы предпочитаете воспроизвести проект самостоятельно, вот шаги с кодом:
- Создайте новое приложение с одним представлением.
- Создать новый
UIView
подкласс (в Objective-C) называетсяNNReadyIndicator
- Скопируйте и вставьте этот код в `NNReadyIndicator.m
#import "NNReadyIndicator.h"
@interface NNReadyIndicator ()
@property CGAffineTransform startTransform;
@property double originalAngle;
@end
@implementation NNReadyIndicator
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
#pragma mark tracking
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
[self setOriginalAngle:[NNReadyIndicator calculateAngleWithX1:touchPoint.x x2:self.center.x y1:touchPoint.y y2:self.center.y]];
[self setStartTransform:self.transform];
NSLog(@"BEGIN TRACKING | originalAngle: %f", self.originalAngle);
return YES;
}
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
double angle = [NNReadyIndicator calculateAngleWithX1:touchPoint.x x2:self.center.x y1:touchPoint.y y2:self.center.y];
CGFloat angleDifference = (CGFloat)(self.originalAngle - angle);
[self setTransform: CGAffineTransformRotate(self.startTransform, -angleDifference)];
NSLog(@"CONTINUE TRACKING | angle: %f angleDifference: %f", angle, angleDifference);
return YES;
}
#pragma mark -- Calculate Angle
+ (double)calculateAngleWithX1:(double)x1 x2:(double)x2 y1:(double)y1 y2:(double)y2 {
double distanceX = [NNReadyIndicator calculateDistanceWithPoint:x1 point:x2];
double distanceY = [NNReadyIndicator calculateDistanceWithPoint:y1 point:y2];
return [self calculateAngleWithDistanceX:distanceX distanceY:distanceY];
}
+ (double)calculateDistanceWithPoint:(double)pointA point:(double)pointB {
double distance = pointA - pointB;
if (distance < 0) {
distance = -distance;
}
return distance;
}
+ (double)calculateAngleWithDistanceX:(double)distanceX distanceY:(double)distanceY {
return atan2(distanceY, distanceX);
}
@end
РЕДАКТИРОВАТЬ: Добавлено ведение журнала
Почему элемент управления не постоянно вращается в одном направлении (и с той же скоростью?), Что и палец, который его тянет?
1 ответ
Вам нужно перевернуть угол, если он выше или ниже 360 градусов. Кроме того, чтобы его было легче понять, вам придется конвертировать его в градусы, а затем обратно. Исходя из этого ответа: /questions/19557237/cgaffinetransformmakerotation-idet-v-druguyu-storonu-posle-180-gradusov-314/19557247#19557247
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
double angle = [NNReadyIndicator calculateAngleWithX1:touchPoint.x x2:self.center.x y1:touchPoint.y y2:self.center.y];
double angleInDegrees = angle * 180 / M_PI;
// Flip angle if above or below 360 degrees
if (angleInDegrees > 180) {
angleInDegrees -= 360;
} else if (angleInDegrees < -180) {
angleInDegrees += 360;
}
CGFloat angleDifference = (CGFloat)(self.originalAngle - angleInDegrees);
[self.layer setTransform: CATransform3DRotate(self.layer.transform, (float)DEGREES_TO_RADIANS(-angleDifference), .0, .0, 1.0)];
NSLog(@"CONTINUE TRACKING | angle: %f angleDifference: %f", angleInRadians, angleDifference);
return YES;
}