2013-07-29 8 views
5

Wykonuję aplikację prędkościomierza i chcę, aby strzałka zachowywała się w prawidłowy sposób - jeśli uruchomię od zera do 200 km w ciągu jednej sekundy, chcę, aby okrążyła poprzeczkę, ale jeśli ustawię wystarczająco duży kąt obrotu, idzie krótko, od dołu.
Jak sprawić, by działało prawie na pełne koło, a nie przez krótką ścieżkę?Obracanie UIView z CGAffineTransform - jak sprawić, by działał na pełną ścieżkę, a nie na krótką?

Oto (trywialne) kod używać do obrotu:

[UIView animateWithDuration:0.3 animations:^(){ 

     self.arrow.transform = CGAffineTransformRotate(CGAffineTransformIdentity, -4.4); 

    }]; 

I postać może obrócić go w małych kawałkach, ale czasami może być konieczne, aby obrócić go szybko od zera do maksimum (na przykład gdybyśmy nie mieli prędkości czytania i osiągnęli już dużą prędkość, więc musimy obrócić strzałkę na większości ekranu).

Jako pytanie poboczne - w jaki sposób mogę umieścić w kolejce animacje, aby można je było zastosować jeden po drugim?

Odpowiedz

3

Miałem podobny problem z powrotem. Musiałem tylko obrócić się o 180 stopni, ale czasami potrzebowałem go zgodnie z ruchem wskazówek zegara, czasami przeciwnie do ruchu wskazówek zegara, ale zawsze odwracałem je w obie strony, stąd "obrócona" własność w kodzie.

Trzeba użyć CALayer i CAKeyframeAnimations, a oto kod, który pracował dla mnie:

-(void) showHideSpinnerWithDuration:(float) duration; 
{ 
    CALayer* layer = _spinner.layer; 
    CAKeyframeAnimation* animation; 
    animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; 

    animation.duration = duration; 
    animation.cumulative = YES; 
    animation.repeatCount = 1; 
    animation.removedOnCompletion = NO; 
    animation.fillMode = kCAFillModeForwards; 

    if (_rotated) { 
     animation.values = [NSArray arrayWithObjects: 
          [NSNumber numberWithFloat:DegreesToRadians(180)], 
          [NSNumber numberWithFloat:DegreesToRadians(0)], 
          nil]; 
     self.rotated = NO; 
    } else { 
     animation.values = [NSArray arrayWithObjects: 
          [NSNumber numberWithFloat:DegreesToRadians(0)], 
          [NSNumber numberWithFloat:DegreesToRadians(180)], 
          nil]; 
     self.rotated = YES; 
    } 

    animation.keyTimes = [NSArray arrayWithObjects: 
          [NSNumber numberWithFloat:0.0], 
          [NSNumber numberWithFloat:duration], nil]; 

    animation.timingFunctions = [NSArray arrayWithObjects: 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], nil]; 

    [layer addAnimation:animation forKey:@"transform.rotation.z"]; 
} 
4

Zrobiłem funkcję pomocnika do tego za chwilę z powrotem, który znajduje się poniżej. Zasadniczo, UIKit jest bezużyteczny, musisz zaimportować framework QuartzCore i użyć albo CAKeyframeAnimation, jak zauważył @Paul Cezanne, albo CABasicAnimation, co moim zdaniem poradzi sobie z tym dobrze.

Użycie jest bardzo proste, wystarczy wywołać metodę opisaną poniżej, przesyłając widok obrazu, który chcesz obrócić, żądany obrót w radianach, a czas trwania animacji i widok obrazu będzie prawidłowo animowany. Zawsze będzie trwało to "na długiej drodze", ponieważ w rzeczywistości jest tutaj określony kierunek.

Po przekazaniu dodatnich wartości do animacji obróci się zgodnie z ruchem wskazówek zegara, a następnie naturalnie wartości ujemne spowodują obrót w lewo.

[self rotateView:imageView rotationInRadians:M_PI duration:2.0]; 


- (void)rotateView:(UIImageView *)imageView rotationInRadians:(CGFloat)radians duration:(CFTimeInterval)duration 
{ 
    CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 

    [rotationAnimation setToValue:[NSNumber numberWithFloat:radians]]; 
    [rotationAnimation setDuration:duration]; 
    [rotationAnimation setCumulative:YES]; 
    [rotationAnimation setFillMode:kCAFillModeForwards]; 
    [rotationAnimation setRemovedOnCompletion:NO]; 

    [imageView.layer addAnimation:rotationAnimation forKey:@"gaugeRotationAnimation"]; 
} 
1

SWIFT 3

miałem dokładnie ten sam problem, tu jest moje rozwiązanie w przypadku, gdy ktoś pomaga.

referencyjny warstwa, która zawiera wskaźnik:

@IBOutlet weak var pointerImageView: UIImageView! 

Zdefiniuj zmienną śledzić ostatniej pozycji kursora:

private var meterPointerRadians: CGFloat = 0 

utworzyć funkcję, która wyznacza wartość licznika przy użyciu procent. Przykład: prędkość 50%

func setMeter(dialPercentage: Double) { 

    //define the start and end angles of your speed meter: Eg: from 90 to 180 (semi circle) 
    let meterLowerRangeAngle: Double = 90.0 
    let meterUpperRangeAngle: Double = 180.0 

    //calculate the angle of the pointer in radians 
    let range = meterUpperRangeAngle - meterLowerRangeAngle 
    let angle = (dialPercentage * range/100) + meterLowerRangeAngle 
    let radians: CGFloat = CGFloat(angle * .pi/180) 

    rotatePointer(imageView: self.pointerImageView, rotationInRadians: radians, duration: 1) 

} 

Obracaj wskaźnikiem, zgodnie z ruchem wskazówek zegara lub przeciwnie do ruchu wskazówek zegara, w zależności od ostatniej pozycji wskaźnika.

Powiązane problemy