6

我正在制作一个速度计应用程序,我希望箭头以正确的方式运行 - 如果我在一秒钟内从零发射到 200 公里,我希望它绕着杆转,但如果我将旋转角度设置得足够大,它就会去捷径,从底部。
我怎样才能让它几乎绕一圈而不是通过短路径?

这是我用于旋转的(琐碎)代码:

[UIView animateWithDuration:0.3 animations:^(){

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

    }];

我想我可以小块旋转它,但有时可能需要将它从零快速旋转到最大值(例如,如果我们没有读取速度并且已经高速旋转,所以我们需要大部分时间旋转箭头屏幕)。

作为一个附带问题 - 我如何排队动画,以便我可以一个一个地应用它们?

4

3 回答 3

4

不久前我为此做了一个辅助函数,如下所示。基本上,UIKit 对此毫无用处,您必须导入 QuartzCore 框架并使用CAKeyframeAnimation@Paul Cezanne 指出的,或者CABasicAnimation,我认为它可以很好地处理这个问题。

用法非常简单,只需调用下面详述的方法,传递您想要旋转的图像视图、您想要的弧度旋转以及动画持续时间,您的图像视图就会正确动画。它总是会走“很长的路”,因为这里实际上指定了一个方向。

如果您将正值传递给动画,它将顺时针旋转,然后自然地,负值将导致逆时针旋转。

[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"];
}
于 2013-08-09T23:53:52.910 回答
3

不久前我遇到了类似的问题。我只需要转 180 度,但有时我需要顺时针,有时逆时针,但我总是在它们两者之间来回翻转,因此代码中的“旋转”属性。

您需要使用 CALayer 和 CAKeyframeAnimations,这是对我有用的代码:

-(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"];
}
于 2013-08-06T12:36:09.270 回答
1

斯威夫特 3

我遇到了完全相同的问题,这是我的解决方案,以防它对其他人有所帮助。

引用包含指针的层:

@IBOutlet weak var pointerImageView: UIImageView!

定义一个变量来跟踪最后一个指针位置:

private var meterPointerRadians: CGFloat = 0

创建一个使用百分比设置仪表值的函数。例如: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)

}

根据指针的最后位置顺时针或逆时针旋转指针。

func rotatePointer(imageView: UIImageView, rotationInRadians: CGFloat, duration: CFTimeInterval) {

    let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")

    rotationAnimation.fromValue = meterPointerRadians
    rotationAnimation.toValue = rotationInRadians
    rotationAnimation.duration = duration
    rotationAnimation.isCumulative = true
    rotationAnimation.fillMode = kCAFillModeBoth
    rotationAnimation.isRemovedOnCompletion = false

    imageView.layer.add(rotationAnimation, forKey: "pointerRotationAnimation")
    meterPointerRadians = CGFloat(rotationInRadians)

}
于 2017-05-18T22:39:10.197 回答