iOS 動畫 —— 橡皮筋

接著上一個動畫繼續(xù)學習UIDynamic Animation 相關猿涨,通過 UIGravityBehavior 重力行為、UICollisionBehavior 碰撞行為姆怪、UIAttachmentBehavior吸附行為實現(xiàn)橡皮筋的功能叛赚。

將其創(chuàng)建為 View,通過子 View 逐一設置來特征

  • RubberBaseView -- 初始化 View
  • RubberAttachView -- 增加吸附行為
  • RubberView -- 增加彈性行為
#import <UIKit/UIKit.h>

@interface RubberBaseView : UIView

@property (nonatomic, strong) UIImageView *box;
@property (nonatomic, strong) UIDynamicAnimator *animator;

@end
#import "RubberBaseView.h"

@implementation RubberBaseView

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
        // 設置背景顏色(通過圖片)
        self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"back"]];
        // 設置方塊 橡皮
        _box = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"rubber"]];
        _box.center = self.center;
        [self addSubview: _box];
        
        // 創(chuàng)建UIDynamicAnimator
        _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
    }
    return self;
}

#import "RubberBaseView.h"

@interface RubberAttachView : RubberBaseView

@property (strong, nonatomic) UIAttachmentBehavior *attachment;

@end

#import "RubberAttachView.h"

@implementation RubberAttachView {
     UIImageView          *_imageView;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        
        //  添加拖動手勢
        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
        [self addGestureRecognizer:pan];
        
        //  添加附著行為
        UIOffset offset = UIOffsetMake(-25, -25);
        _attachment = [[UIAttachmentBehavior alloc] initWithItem:self.box offsetFromCenter:offset attachedToAnchor:CGPointMake(self.box.center.x, self.box.center.y - 100)];
        [self.animator addBehavior:_attachment];
        
        //  添加box內(nèi)部錨點圖像
        _imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"lineCircle"]];
        _imageView.center = CGPointMake(self.box.bounds.size.width / 2 + offset.horizontal, self.box.bounds.size.height / 2 + offset.vertical);
        [self.box addSubview:_imageView];
    }
    return self;
}

- (void)pan:(UIPanGestureRecognizer *)gesture {
    
    if (UIGestureRecognizerStateChanged == gesture.state) {
        self.attachment.anchorPoint = [gesture locationInView:self];
        // 重新繪制
        [self setNeedsDisplay];
    }
}

- (void)drawRect:(CGRect)rect
{
    // 上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    // 位置
    CGPoint position = [self convertPoint:_imageView.center fromView:self.box];
    // 設置開始點
    CGContextMoveToPoint(context, position.x, position.y);
    CGContextAddLineToPoint(context, self.attachment.anchorPoint.x, self.attachment.anchorPoint.y);
    // 設置線寬
    CGContextSetLineWidth(context, 5.0f);
    CGFloat length[] = {5.0, 5.0};
    CGContextSetLineDash(context, 0.0, length, 2);
    [[UIColor blackColor] set];
    // 設置路徑
    CGContextDrawPath(context, kCGPathStroke);
}

@end
#import "RubberAttachView.h"

@interface RubberView : RubberAttachView

@end
#import "RubberView.h"

static NSString *const RubberViewCenterKVOName = @"center";

@implementation RubberView

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
        // 設置物理屬性
        self.attachment.damping = 1; // 震蕩
        self.attachment.frequency = 1; // 阻力
        // 設置觀察者稽揭,在手指離開以后繼續(xù)畫線
        [self.box addObserver:self forKeyPath:RubberViewCenterKVOName options:NSKeyValueObservingOptionNew context:nil];
        
        //創(chuàng)建并添加重力
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.box]];
        [self.attachment addChildBehavior:gravity];
        
        //創(chuàng)建并添加碰撞行為對象
        UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.box]];
        collision.translatesReferenceBoundsIntoBoundary = YES;
        [self.attachment addChildBehavior:collision];
    }
    return self;
}

- (void)dealloc {
    [self.box removeObserver:self forKeyPath:RubberViewCenterKVOName];
}

//畫線
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:RubberViewCenterKVOName]) {
        [self setNeedsDisplay];
    }
    
}
@end

最后實現(xiàn)

#import "ViewController.h"
#import "RubberView.h"

#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (nonatomic, strong) RubberView *rubberView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.rubberView];
}

- (RubberView *)rubberView  {
    if (!_rubberView) {
        _rubberView = [[RubberView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    }
    return _rubberView;
}

@end

注意點1: 此處為什么要通過 子類的 View(繼承) 逐一去設置呢俺附?

  • 方便理解,一目了解
  • 不改變原來的基礎上溪掀,拓充方法事镣,擴充功能性強。

當然此處也可以不這樣寫咯揪胃。

注意點2: UIAttachmentBehavior

附著行為璃哟,讓物體附著在某個點或另外一個物體上≈幌可以設置附著點的到物體的距離沮稚,阻尼系數(shù)和振動頻率等。

_attachment = [[UIAttachmentBehavior alloc] initWithItem:self.box offsetFromCenter:offset attachedToAnchor:CGPointMake(self.box.center.x, self.box.center.y - 100)];

注意這個初始化中方法的offset 和 point 的設置(就是決定線和 box 位置和距離的)册舞,當然UIAttachmentBehavior 還有其他的初始化方法蕴掏,可以根據(jù)不同場景相應使用。

- (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
- (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point NS_DESIGNATED_INITIALIZER;

- (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
- (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2 NS_DESIGNATED_INITIALIZER;

PS:場景來自:【iOS開發(fā)范例實戰(zhàn)寶典.進階篇】调鲸。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盛杰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子藐石,更是在濱河造成了極大的恐慌即供,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件于微,死亡現(xiàn)場離奇詭異逗嫡,居然都是意外死亡,警方通過查閱死者的電腦和手機株依,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門驱证,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恋腕,你說我怎么就攤上這事抹锄。” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵伙单,是天一觀的道長获高。 經(jīng)常有香客問我,道長吻育,這世上最難降的妖魔是什么念秧? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮扫沼,結果婚禮上出爹,老公的妹妹穿的比我還像新娘。我一直安慰自己缎除,他們只是感情好严就,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著器罐,像睡著了一般梢为。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轰坊,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天铸董,我揣著相機與錄音,去河邊找鬼肴沫。 笑死粟害,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的颤芬。 我是一名探鬼主播悲幅,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼站蝠!你這毒婦竟也來了汰具?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤菱魔,失蹤者是張志新(化名)和其女友劉穎留荔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澜倦,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡聚蝶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了藻治。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碘勉。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖栋艳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情句各,我是刑警寧澤吸占,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布晴叨,位于F島的核電站,受9級特大地震影響矾屯,放射性物質(zhì)發(fā)生泄漏兼蕊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一件蚕、第九天 我趴在偏房一處隱蔽的房頂上張望孙技。 院中可真熱鬧,春花似錦排作、人聲如沸牵啦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哈雏。三九已至,卻和暖如春衫生,著一層夾襖步出監(jiān)牢的瞬間裳瘪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工罪针, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留彭羹,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓泪酱,卻偏偏與公主長得像派殷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子西篓,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本文中所有代碼演示均有GitHub源碼愈腾,點擊下載 UIDynamic簡介 簡介:UIKit動力學最大的特點是將現(xiàn)實...
    si1ence閱讀 10,225評論 8 79
  • 前言: UIKit Dynamics是iOS7.0新增的一組類和方法,可以賦予UIView逼真的行為和特征岂津,從而改...
    Y_小蔥閱讀 650評論 1 1
  • 概念介紹 UIDynamic從ios7才開始有的虱黄,其他2D仿真引擎:BOX2D:C語言框架,免費Chipmunk:...
    我是滕先生閱讀 2,252評論 5 23
  • 寫了一些不敢寫 沒良心的話 可那是我的真實想法 怕什么呢 那日記不會給誰看 別說不愿說 寫也不愿些 欣喜的是 我慢...
    桔樹上閱讀 114評論 0 2
  • 1.OpenCL概念 OpenCL是一個為異構平臺編寫程序的框架吮成,此異構平臺可由CPU橱乱、GPU或其他類型的處理器組...
    snoopy_zc閱讀 33,597評論 2 18