需求概述:
偶然发现网易云音乐app播放界面的唱片可以用手拨动旋转,觉得这个效果非常赞,
也想实现后加到自家app里面, 于是研究了一下其实现方法
最终效果:
项目结构如下:
新建一个storyboard如下:
定义KTOneFingerRotationGestureRecognizer
这儿使用到了一个第3方的类: KTOneFingerRotationGestureRecognizer
KTOneFingerRotationGestureRecognizer.h
#import <UIKit/UIKit.h>
@interface KTOneFingerRotationGestureRecognizer : UIGestureRecognizer
{
}
/**
The rotation of the gesture in radians since its last change.
*/
@property (nonatomic, assign) CGFloat rotation;
@end
KTOneFingerRotationGestureRecognizer.m
#import "KTOneFingerRotationGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
@implementation KTOneFingerRotationGestureRecognizer
@synthesize rotation = rotation_;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Fail when more than 1 finger detected.
if ([[event touchesForGestureRecognizer:self] count] > 1) {
[self setState:UIGestureRecognizerStateFailed];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self state] == UIGestureRecognizerStatePossible) {
[self setState:UIGestureRecognizerStateBegan];
} else {
[self setState:UIGestureRecognizerStateChanged];
}
// We can look at any touch object since we know we
// have only 1. If there were more than 1 then
// touchesBegan:withEvent: would have failed the recognizer.
UITouch *touch = [touches anyObject];
// To rotate with one finger, we simulate a second finger.
// The second figure is on the opposite side of the virtual
// circle that represents the rotation gesture.
UIView *view = [self view];
CGPoint center = CGPointMake(CGRectGetMidX([view bounds]), CGRectGetMidY([view bounds]));
CGPoint currentTouchPoint = [touch locationInView:view];
CGPoint previousTouchPoint = [touch previousLocationInView:view];
CGFloat angleInRadians = atan2f(currentTouchPoint.y - center.y, currentTouchPoint.x - center.x) - atan2f(previousTouchPoint.y - center.y, previousTouchPoint.x - center.x);
[self setRotation:angleInRadians];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Perform final check to make sure a tap was not misinterpreted.
if ([self state] == UIGestureRecognizerStateChanged) {
[self setState:UIGestureRecognizerStateEnded];
} else {
[self setState:UIGestureRecognizerStateFailed];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setState:UIGestureRecognizerStateFailed];
}
@end
使用KTOneFingerRotationGestureRecognizer
只需要在自己的控制器中作如下调用,即可实现期望效果:
//
// ViewController.m
// 16OneFingerRotation
//
// Created by beyond on 2018/1/2.
// Copyright © 2018年 beyond. All rights reserved.
//
#import "ViewController.h"
#import "KTOneFingerRotationGestureRecognizer.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self addOneTapGuesture];
}
- (void)addOneTapGuesture
{
self.postImgView.userInteractionEnabled = YES;
// 海报
[self addRotationGestureToView:self.postImgView];
[self addTapGestureToView:self.postImgView numberOfTaps:1];
}
- (void)addRotationGestureToView:(UIView *)view
{
KTOneFingerRotationGestureRecognizer *rotation = [[KTOneFingerRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotatingGuestureReco:)];
[view addGestureRecognizer:rotation];
}
- (void)addTapGestureToView:(UIView *)view numberOfTaps:(NSInteger)numberOfTaps
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedGuestureReco:)];
[tap setNumberOfTapsRequired:numberOfTaps];
[view addGestureRecognizer:tap];
}
- (void)rotatingGuestureReco:(KTOneFingerRotationGestureRecognizer *)recognizer
{
UIView *view = [recognizer view];
[view setTransform:CGAffineTransformRotate([view transform], [recognizer rotation])];
}
- (void)tappedGuestureReco:(UITapGestureRecognizer *)recognizer
{
UIView *view = [recognizer view];
[view setTransform:CGAffineTransformMakeRotation(0)];
}
@end
附录: 项目中使用到的图片素材:
海报使用的图片是鼎鼎大名的白金迪斯科,
在Storyboard中,该ImageView的宽高约束是180 * 180个点
黑白唱片大小是:713 * 713pix, 其中内环是:460pix
因此, 黑白唱片的宽高 约束, 应该是 713 * 180 / 460 – (5个点的修正系数) = 274个点
附录: github源码 下载地址
未完待续,下一章节,つづく