2010-09-21 14 views
5

Estoy tratando de hacer girar una imagen circular en función del deslizamiento del usuario. Ahora lo he hecho considerando las dos partes. uno es el lado izquierdo y el otro es el lado derecho. Si el usuario se desliza hacia abajo desde la mitad derecha, significa que gira en el sentido de las agujas del reloj y deslizar hacia arriba significa anti horario. En el lado izquierdo, he hecho el viceversa. Así que ahora mi imagen girará bien solo cuando toco la mitad izquierda y derecha ... al tocar arriba y abajo ... su comportamiento es diferente. Incluso he intentado ny el cálculo de los radianes .. su también no trabajar Puede alguien me sugieren para identificar las agujas del reloj o Antihor sabia de una mejor manera ...Cómo puedo hacer que una imagen gire en función de la dirección de deslizamiento de mi dedo

gracias u, Lakshmi Jones

Respuesta

1

Tienes alguna vez has probado this tutorial para tu problema. Esto te ayudará con seguridad.

El archivo .h para calcular el golpe

#import <UIKit/UIKit.h> 
#import "SMRotaryProtocol.h" 

@interface SMRotaryWheel : UIControl 

@property (weak) id <SMRotaryProtocol> delegate; 
@property (nonatomic, strong) UIView *container; 
@property int numberOfSections; 
@property CGAffineTransform startTransform; 
@property (nonatomic, strong) NSMutableArray *cloves; 
@property int currentValue; 


- (id) initWithFrame:(CGRect)frame andDelegate:(id)del withSections:(int)sectionsNumber; 

y el archivo .m es

#import "SMRotaryWheel.h" 
#import <QuartzCore/QuartzCore.h> 
#import "SMCLove.h" 

@interface SMRotaryWheel() 
    - (void)drawWheel; 
    - (float) calculateDistanceFromCenter:(CGPoint)point; 
    - (void) buildClovesEven; 
    - (void) buildClovesOdd; 
    - (UIImageView *) getCloveByValue:(int)value; 
    - (NSString *) getCloveName:(int)position; 
@end 

static float deltaAngle; 
static float minAlphavalue = 0.6; 
static float maxAlphavalue = 1.0; 

@implementation SMRotaryWheel 

@synthesize delegate, container, numberOfSections, startTransform, cloves, currentValue; 


- (id) initWithFrame:(CGRect)frame andDelegate:(id)del withSections:(int)sectionsNumber { 

    if ((self = [super initWithFrame:frame])) { 

     self.currentValue = 0; 
     self.numberOfSections = sectionsNumber; 
     self.delegate = del; 
     [self drawWheel]; 

    } 
    return self; 
} 



- (void) drawWheel { 

    container = [[UIView alloc] initWithFrame:self.frame]; 

    CGFloat angleSize = 2*M_PI/numberOfSections; 

    for (int i = 0; i < numberOfSections; i++) { 

     UIImageView *im = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"segment.png"]]; 

     im.layer.anchorPoint = CGPointMake(1.0f, 0.5f); 
     im.layer.position = CGPointMake(container.bounds.size.width/2.0-container.frame.origin.x, 
             container.bounds.size.height/2.0-container.frame.origin.y); 
     im.transform = CGAffineTransformMakeRotation(angleSize*i); 
     im.alpha = minAlphavalue; 
     im.tag = i; 

     if (i == 0) { 
      im.alpha = maxAlphavalue; 
     } 

     UIImageView *cloveImage = [[UIImageView alloc] initWithFrame:CGRectMake(12, 15, 40, 40)]; 
     cloveImage.image = [UIImage imageNamed:[NSString stringWithFormat:@"icon%i.png", i]]; 
     [im addSubview:cloveImage]; 

     [container addSubview:im]; 

    } 

    container.userInteractionEnabled = NO; 
    [self addSubview:container]; 

    cloves = [NSMutableArray arrayWithCapacity:numberOfSections]; 

    UIImageView *bg = [[UIImageView alloc] initWithFrame:self.frame]; 
    bg.image = [UIImage imageNamed:@"bg.png"]; 
    [self addSubview:bg]; 

    UIImageView *mask = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 58, 58)]; 
    mask.image =[UIImage imageNamed:@"centerButton.png"] ; 
    mask.center = self.center; 
    mask.center = CGPointMake(mask.center.x, mask.center.y+3); 
    [self addSubview:mask]; 

    if (numberOfSections % 2 == 0) { 

     [self buildClovesEven]; 

    } else { 

     [self buildClovesOdd]; 

    } 

    [self.delegate wheelDidChangeValue:[self getCloveName:currentValue]]; 


} 


- (UIImageView *) getCloveByValue:(int)value { 

    UIImageView *res; 

    NSArray *views = [container subviews]; 

    for (UIImageView *im in views) { 

     if (im.tag == value) 
      res = im; 

    } 

    return res; 

} 

- (void) buildClovesEven { 

    CGFloat fanWidth = M_PI*2/numberOfSections; 
    CGFloat mid = 0; 

    for (int i = 0; i < numberOfSections; i++) { 

     SMClove *clove = [[SMClove alloc] init]; 
     clove.midValue = mid; 
     clove.minValue = mid - (fanWidth/2); 
     clove.maxValue = mid + (fanWidth/2); 
     clove.value = i; 


     if (clove.maxValue-fanWidth < - M_PI) { 

      mid = M_PI; 
      clove.midValue = mid; 
      clove.minValue = fabsf(clove.maxValue); 

     } 

     mid -= fanWidth; 


     NSLog(@"cl is %@", clove); 

     [cloves addObject:clove]; 

    } 

} 


- (void) buildClovesOdd { 

    CGFloat fanWidth = M_PI*2/numberOfSections; 
    CGFloat mid = 0; 

    for (int i = 0; i < numberOfSections; i++) { 

     SMClove *clove = [[SMClove alloc] init]; 
     clove.midValue = mid; 
     clove.minValue = mid - (fanWidth/2); 
     clove.maxValue = mid + (fanWidth/2); 
     clove.value = i; 

     mid -= fanWidth; 

     if (clove.minValue < - M_PI) { 

      mid = -mid; 
      mid -= fanWidth; 

     } 


     [cloves addObject:clove]; 

     NSLog(@"cl is %@", clove); 

    } 

} 

- (float) calculateDistanceFromCenter:(CGPoint)point { 

    CGPoint center = CGPointMake(self.bounds.size.width/2.0f, self.bounds.size.height/2.0f); 
    float dx = point.x - center.x; 
    float dy = point.y - center.y; 
    return sqrt(dx*dx + dy*dy); 

} 

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 

    CGPoint touchPoint = [touch locationInView:self]; 
    float dist = [self calculateDistanceFromCenter:touchPoint]; 

    if (dist < 40 || dist > 100) 
    { 
     // forcing a tap to be on the ferrule 
     NSLog(@"ignoring tap (%f,%f)", touchPoint.x, touchPoint.y); 
     return NO; 
    } 

    float dx = touchPoint.x - container.center.x; 
    float dy = touchPoint.y - container.center.y; 
    deltaAngle = atan2(dy,dx); 

    startTransform = container.transform; 

    UIImageView *im = [self getCloveByValue:currentValue]; 
    im.alpha = minAlphavalue; 

    return YES; 

} 

- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event 
{ 

    CGPoint pt = [touch locationInView:self]; 

    float dist = [self calculateDistanceFromCenter:pt]; 

    if (dist < 40 || dist > 100) 
    { 
     // a drag path too close to the center 
     NSLog(@"drag path too close to the center (%f,%f)", pt.x, pt.y); 

     // here you might want to implement your solution when the drag 
     // is too close to the center 
     // You might go back to the clove previously selected 
     // or you might calculate the clove corresponding to 
     // the "exit point" of the drag. 

    } 

    float dx = pt.x - container.center.x; 
    float dy = pt.y - container.center.y; 
    float ang = atan2(dy,dx); 

    float angleDifference = deltaAngle - ang; 

    container.transform = CGAffineTransformRotate(startTransform, -angleDifference); 

    return YES; 

} 

- (void)endTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event 
{ 

    CGFloat radians = atan2f(container.transform.b, container.transform.a); 

    CGFloat newVal = 0.0; 

    for (SMClove *c in cloves) { 

     if (c.minValue > 0 && c.maxValue < 0) { // anomalous case 

      if (c.maxValue > radians || c.minValue < radians) { 

       if (radians > 0) { // we are in the positive quadrant 

        newVal = radians - M_PI; 

       } else { // we are in the negative one 

        newVal = M_PI + radians;      

       } 
       currentValue = c.value; 

      } 

     } 

     else if (radians > c.minValue && radians < c.maxValue) { 

      newVal = radians - c.midValue; 
      currentValue = c.value; 

     } 

    } 

    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.2]; 

    CGAffineTransform t = CGAffineTransformRotate(container.transform, -newVal); 
    container.transform = t; 

    [UIView commitAnimations]; 

    [self.delegate wheelDidChangeValue:[self getCloveName:currentValue]]; 

    UIImageView *im = [self getCloveByValue:currentValue]; 
    im.alpha = maxAlphavalue; 

} 

- (NSString *) getCloveName:(int)position { 

    NSString *res = @""; 

    switch (position) { 
     case 0: 
      res = @"Circles"; 
      break; 

     case 1: 
      res = @"Flower"; 
      break; 

     case 2: 
      res = @"Monster"; 
      break; 

     case 3: 
      res = @"Person"; 
      break; 

     case 4: 
      res = @"Smile"; 
      break; 

     case 5: 
      res = @"Sun"; 
      break; 

     case 6: 
      res = @"Swirl"; 
      break; 

     case 7: 
      res = @"3 circles"; 
      break; 

     case 8: 
      res = @"Triangle"; 
      break; 

     default: 
      break; 
    } 

    return res; 
} 



@end 

principales métodos que le ayudarán a realizar el seguimiento del golpe son

- (float) calculateDistanceFromCenter:(CGPoint)point 

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event 

- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event 

- (void)endTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event 

Que esto te ayude :)

5

Debería abordar este problema con la trignometría. Suponiendo que conoce el punto de partida de golpe (A1, B1) y el punto de golpe final (a2, b2) El centro de los círculos está en (x, y)

enter image description here

Si conocemos la diferencia de ángulos formados por líneas (x, y) -> (a1, b1) y (x, y) -> (a2, b2) sabremos si rotar en sentido horario o antihorario en función de si dicho ángulo es positivo o negativo.

El ángulo formado por una línea se calcula a continuación. Deje que el ángulo sea de color rojo rojo

if(a1-x==0){ 
    if(b1-y>0) red=pi/2 
    else red = 3*pi/2 
} 
else{ 
    tan(red) = abs((b1-y)/(a1-x)) 
    red = tan-inverse(abs((b1-y)/(a1-x))) 
    if(a1-x<0){ 
    if(b1-y<=0) 
     red+=pi; 
    else 
     red+=pi/2 
    } 
    else if(a1-x>0 && b1-y<0){ 
     red+=3*pi/2 
    } 
} 

Ver here saber cómo calcular tan-inversa.

De manera similar, calcule el valor del ángulo verde. Después de hacer eso, simplemente comparar el valor de verde y rojo le permitirá saber qué hacer.

if(red - green == pi || red - green == 0){ 
    do_nothing();   
}else if(red - green > 0){ 
    rotate_clockwise();   
}else{ 
    rotate_anticlockwise(); 
} 

Mediante el uso de los datos de aceleración/velocidad del golpe que podría girar el círculo con la misma aceleración/velocidad.

0

Aunque la trigonometría es un enfoque matemático, es más simple y requiere mucha menos potencia de procesador para hacer esto con los vectores.

Un cuadro para la referencia:

enter image description here

El centro de la rápida que desea girar es el punto C.

Desde la interfaz de usuario que debe tener un punto de inicio golpe Un y "vector golpe" s que muestra cómo el dedo del usuario está en movimiento. Si el sistema operativo proporciona sólo un segundo punto B algún tiempo después de Un, a continuación, calcular s = B - Un.

desea calcular el componente de s que es tangente al círculo con centro en C pasando por Un. Esto le permitirá al usuario iniciar su deslizamiento en cualquier lugar y hacer que se lo trate como un par sobre el punto C. Esto debería ser intuitivo.

Esto no es difícil. El radio del círculo se muestra como vector r = A - C. La perpendicular a este vector se llama "r perp", que se muestra con el símbolo "chincheta" en la imagen. Es solo el punto (-y, x) donde xey son los componentes de r.

La longitud firmado de la proyección de p en perp (r) es sólo un producto de punto normalizada:

enter image description here

Este es un escalar que es positiva si la rotación es en sentido antihorario alrededor C y negativo si es en el sentido de las agujas del reloj. Entonces el letrero te dice la dirección de rotación. El valor absoluto te dice cuánto o qué tan rápido girar.

Supongamos que ya hemos deslizar vector s almacenada como sx y sy y el centro C como cx y cy. A continuación, el pseudo código es simplemente:

r_perp_x = cy - ay; r_perp_y = ax - cx; 
signed_length_p = (sx * r_perp_x + sy * r_perp_y)/sqrt(r_perp_x^2 + r_perp_y^2) 

El número deseado es signed_length_p.

La única advertencia es ignorar toques A que están cerca de C. Pueden producir valores de salida muy grandes o división por cero. Esto es fácil de arreglar. Simplemente verifique la longitud de r y salga si es inferior a algún valor razonable.

0

Si su solución actual es "casi buena" para usted, lo más simple sería ...simplemente fijándolo con dos áreas más: starting swipe areas

Ahora usted hace girar su imagen hacia la derecha cada vez que el usuario se pasó
- derecha o arriba (iniciado en la zona A)
- derecha o hacia abajo (iniciado en el área B)
- la izquierda o hacia abajo (iniciado en el área D)
- izquierda o hacia arriba (iniciado en la zona C)

.... más - girar en sentido antihorario.

Cuestiones relacionadas