iOS_单指拨动唱片旋转效果

需求概述:

偶然发现网易云音乐app播放界面的唱片可以用手拨动旋转,觉得这个效果非常赞,

也想实现后加到自家app里面, 于是研究了一下其实现方法

最终效果:

iOS_单指转动唱片效果
iOS_单指转动唱片效果

项目结构如下:

新建一个storyboard如下:

iOS_单指拨动唱片旋转效果_Storyboard布局
iOS_单指拨动唱片旋转效果_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个

 

使用PS生成的黑白胶片
使用PS生成的黑白胶片

黑白唱片大小是:713 *  713pix,  其中内环是:460pix

因此, 黑白唱片的宽高 约束, 应该是 713 * 180 / 460  – (5个点的修正系数)  = 274个


附录: github源码 下载地址

iOS_单指转动唱片效果

 

 

 

未完待续,下一章节,つづく