使用 CADisplayLink 的 UIImageView 旋转动画 - 跟踪旋转
UIImageView Rotation Animation using CADisplayLink - Tracking Rotation
有人建议我尝试 CADisplayLink
旋转 UIIMageView
。我正在使用 Storyboard 构建此应用。
我需要在点击屏幕时开始和停止动画。我还需要跟踪点击屏幕时旋转停止的角度。
我找到了这个教程HERE,但它对我帮助不大。
我还找到了几个小例子 (here's one),但我无法让它真正动起来。从我从上面的例子中得到的,我的图像旋转了一次,然后就停止了。
除此之外,我真的找不到一个很好的教程或示例来说明如何使用 CADisplayLink
连续旋转我的 UIImageView
,直到被点击,然后再次被点击时继续旋转,最终存储旋转角度。
为了让您了解我要实现的目标,它基本上是一个钟面,当钟针旋转时,您可以通过点击来启动和停止它,并检索角度。
有谁知道一个很好的例子吗?或者也许可以帮我解决这个问题。谢谢。
更新/编辑
在我的应用程序中使用下面 Rob 的出色 Obj-C 答案效果很好。
如果有人感兴趣,这就是我跟踪旋转角度并将其显示在屏幕上的方式:
每次调用HandleDisplayLink
时,我都调用了这个方法:[self calculateDisplayAngle];
方法很简单:
- (void)calculateDisplayAngle{
currentRotationAngle = self.percent*360; //360 because I changed kDuration = 1;
self.AngleLabel.text = [NSString stringWithFormat:@"Angle: %.2f",currentRotationAngle];
}
您可以只拥有跟踪旋转状态的属性,这样当您停止旋转时,它可以从停止的地方继续。例如:
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
startDisplayLink()
}
@IBAction func handleTapGesture(sender: UITapGestureRecognizer) {
if displayLink != nil {
stopDisplayLink()
} else {
startDisplayLink()
}
}
private let duration = 2.5
private var percent = 0.0
private var displayLink: CADisplayLink?
private var start: CFAbsoluteTime?
func startDisplayLink() {
displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
start = CFAbsoluteTimeGetCurrent() + (1.0 - percent) * duration
displayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
}
func handleDisplayLink(displayLink: CADisplayLink) {
let elapsed = CFAbsoluteTimeGetCurrent() - start!
percent = (elapsed % duration) / duration
imageView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 2.0 * percent))
}
或 Objective-C:
static CGFloat const kDuration = 2.5;
@interface ViewController2 ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CFAbsoluteTime startTime;
@property (nonatomic) CGFloat percent;
@end
@implementation ViewController2
- (IBAction)handleTapGesture:(UITapGestureRecognizer *)sender {
if (self.displayLink) {
[self stopDisplayLink];
} else {
[self startDisplayLink];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[self startDisplayLink];
// Do any additional setup after loading the view.
}
- (void)startDisplayLink {
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
self.startTime = CFAbsoluteTimeGetCurrent() + (1.0 - self.percent) * kDuration;
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)stopDisplayLink {
[self.displayLink invalidate];
self.displayLink = nil;
}
- (void)handleDisplayLink:(CADisplayLink *)displayLink {
CFAbsoluteTime elapsed = CFAbsoluteTimeGetCurrent() - self.startTime;
self.percent = elapsed / kDuration - floor(elapsed / kDuration);
self.imageView.transform = CGAffineTransformMakeRotation(M_PI * 2.0 * self.percent);
}
@end
有人建议我尝试 CADisplayLink
旋转 UIIMageView
。我正在使用 Storyboard 构建此应用。
我需要在点击屏幕时开始和停止动画。我还需要跟踪点击屏幕时旋转停止的角度。
我找到了这个教程HERE,但它对我帮助不大。
我还找到了几个小例子 (here's one),但我无法让它真正动起来。从我从上面的例子中得到的,我的图像旋转了一次,然后就停止了。
除此之外,我真的找不到一个很好的教程或示例来说明如何使用 CADisplayLink
连续旋转我的 UIImageView
,直到被点击,然后再次被点击时继续旋转,最终存储旋转角度。
为了让您了解我要实现的目标,它基本上是一个钟面,当钟针旋转时,您可以通过点击来启动和停止它,并检索角度。
有谁知道一个很好的例子吗?或者也许可以帮我解决这个问题。谢谢。
更新/编辑
在我的应用程序中使用下面 Rob 的出色 Obj-C 答案效果很好。 如果有人感兴趣,这就是我跟踪旋转角度并将其显示在屏幕上的方式:
每次调用HandleDisplayLink
时,我都调用了这个方法:[self calculateDisplayAngle];
方法很简单:
- (void)calculateDisplayAngle{
currentRotationAngle = self.percent*360; //360 because I changed kDuration = 1;
self.AngleLabel.text = [NSString stringWithFormat:@"Angle: %.2f",currentRotationAngle];
}
您可以只拥有跟踪旋转状态的属性,这样当您停止旋转时,它可以从停止的地方继续。例如:
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
startDisplayLink()
}
@IBAction func handleTapGesture(sender: UITapGestureRecognizer) {
if displayLink != nil {
stopDisplayLink()
} else {
startDisplayLink()
}
}
private let duration = 2.5
private var percent = 0.0
private var displayLink: CADisplayLink?
private var start: CFAbsoluteTime?
func startDisplayLink() {
displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
start = CFAbsoluteTimeGetCurrent() + (1.0 - percent) * duration
displayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
}
func handleDisplayLink(displayLink: CADisplayLink) {
let elapsed = CFAbsoluteTimeGetCurrent() - start!
percent = (elapsed % duration) / duration
imageView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 2.0 * percent))
}
或 Objective-C:
static CGFloat const kDuration = 2.5;
@interface ViewController2 ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CFAbsoluteTime startTime;
@property (nonatomic) CGFloat percent;
@end
@implementation ViewController2
- (IBAction)handleTapGesture:(UITapGestureRecognizer *)sender {
if (self.displayLink) {
[self stopDisplayLink];
} else {
[self startDisplayLink];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[self startDisplayLink];
// Do any additional setup after loading the view.
}
- (void)startDisplayLink {
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
self.startTime = CFAbsoluteTimeGetCurrent() + (1.0 - self.percent) * kDuration;
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)stopDisplayLink {
[self.displayLink invalidate];
self.displayLink = nil;
}
- (void)handleDisplayLink:(CADisplayLink *)displayLink {
CFAbsoluteTime elapsed = CFAbsoluteTimeGetCurrent() - self.startTime;
self.percent = elapsed / kDuration - floor(elapsed / kDuration);
self.imageView.transform = CGAffineTransformMakeRotation(M_PI * 2.0 * self.percent);
}
@end