pop动画框架源码初步探究

pop架构

由四大部分组成

1.Animations

2.Engine

3.Utility

4.WebCore

第一部分Animations

这一部分当中定义了动画的类型,一共4种,分别是:

POPBasicAnimation        //基本动画固定时间间隔

POPCustomAnimation    //自定义动画

POPDecayAnimation      //带阻尼动画效果

POPSpringAnimation     //弹簧动画效果

各自有不同的使用场景

再看一下此目录中的类继承的结构关系

POPAnimation

———> POPPropertyAnimation

———>POPBasicAnimation

———>POPDecayAnimation

———>POPSpringAnimation

———>POPCustomAnimation

POPAnimation中定义了各种动画中需要的公有属性

name beginTime tracer block 以及相应的代理回调,类扩展等等,以及引用了POPAnimationInternal中的私有结构体等(_POPAnimationState)

basic动画示例

spring动画

想了下,写这些东西网上随便都能查的到啊,这样还是看看源码pop如何具体实现一个动画效果的,所以请抛开上面所说的Animations框架主题

先从一个最基本的basic动画的创建开始

1. POPBasicAnimation *anBasic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionX];

2. anBasic.toValue = @(testView.center.y+50);

3. anBasic.beginTime = CACurrentMediaTime()+2.0f;

4. [testView pop_addAnimation:anBasic forKey:@"position"];

先看一下代码的执行流程

POPBasicAnimation *anBasic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionX];

然后进入到这个方法

1.

+ (instancetype)animationWithPropertyNamed:(NSString*)aName

{

POPBasicAnimation*anim = [selfanimation];

anim.property= [POPAnimatable PropertypropertyWithName:aName];//跳入2中

return anim;

}

(POPBasicAnimation)

2.

+ (id)propertyWithName:(NSString*)aName

{

return[self propertyWithName:aNameinitializer:NULL];//跳入3中

}

(POPAnimatableProperty)

3.

/**

* 返回要进行的动画属性

*

*  @param aName  属性名称

*  @param aBlock

*

*  @return <#return value description#>

*/

+ (id)propertyWithName:(NSString*)aName initializer:(void(^)(POPMutableAnimatableProperty*prop))aBlock

{

POPAnimatableProperty*prop =nil;//声明一个空的POPAnimatableProperty对象

staticNSMutableDictionary*_propertyDict =nil;

if(nil== _propertyDict) {

_propertyDict = [[NSMutableDictionary alloc]initWithCapacity:10];//实例化一个静态可变字典

}

prop = _propertyDict[aName];

if(nil!= prop) {

returnprop;//如果prop不等于nil则返回prop

}

NSUIntegerstaticIdx =staticIndexWithName(aName);//如果prop为nil,则通过此函数定位下标

if(NSNotFound!= staticIdx) {

//如果下标不为NSNotFound,则新建一个POPStaticAnimatableProperty对象

POPStaticAnimatableProperty*staticProp = [[POPStaticAnimatableProperty alloc]init];

//让新建对象的结构体指向通过下标根据结构体数组找到的结构体(语言组织有点问题)

staticProp->_state= &_staticStates[staticIdx];

//添加字典中的key-value,key是aName,Value是POPStaticAnimatableProperty对象

_propertyDict[aName] = staticProp;

prop = staticProp;

}else if(NULL!= aBlock) {

//如果block参数不为空,则创建POPMutableAnimatableProperty对象

POPMutableAnimatableProperty*mutableProp =[[POPMutableAnimatableProperty alloc]init];

mutableProp.name= aName;

mutableProp.threshold=1.0;

aBlock(mutableProp);执行block

prop = [mutableProp copy];

}

return prop;

}

接着

anBasic.toValue = @(testView.center.y+50);

执行

- (void)setToValue:(id)aValue

{

POPPropertyAnimationState*s =__state;

VectorRefvec =POPUnbox(aValue, s->valueType, s->valueCount,YES);//解包一个向量,把point,size ,rect,color对象转换为vector

//vector的各种逻辑判断

if(!vec_equal(vec, s->toVec)) {

s->toVec= vec;

// invalidate to dependent state

s->didReachToValue=false;

s->distanceVec=NULL;

if(s->tracing) {

//把动画过程中的属性变化加入追踪器,生成event加入events数组中

[s->tracerupdateToValue:aValue];

}

// automatically unpause active animations

if(s->active&& s->paused) {

s->setPaused(false);

}

}

}

最后看一下

[testViewpop_addAnimation:anBasicforKey:@"position"];

是如何把一个animation加到view上一个动画就能够动起来

先看一下都调用了哪些方法

- (void)pop_addAnimation:(POPAnimation*)anim forKey:(NSString*)key

{

[[POPAnimator sharedAnimator]addAnimation:anim forObject:self key:key];

}

继续...

+ (id)sharedAnimator

{

staticPOPAnimator* _animator =nil;

staticdispatch_once_tonceToken;

dispatch_once(&onceToken, ^{

_animator = [[POPAnimator alloc] init];

});

return_animator;

}

继续

- (id)init

{

self= [super init];

if(nil==self)return nil;

#if TARGET_OS_IPHONE

_displayLink= [CADisplayLink displayLinkWithTarget:self selector:@selector(render)];

//这个时候为pause状态为yes动画还没开始跑

_displayLink.paused=YES;

[_displayLink addToRunLoop:[NSRunLoop mainRunLoop]forMode:NSRunLoopCommonModes];

#else

CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);

CVDisplayLinkSetOutputCallback(_displayLink, displayLinkCallback, (__bridgevoid*)self);

#endif

_dict=POPDictionaryCreateMutableWeakPointerToStrongObject(5);

_lock=OS_SPINLOCK_INIT;

returnself;

}

看见没在这里创建了一个CADisplayLink对象(关于CADisplayLink是个什么东西,可以自行google)

重点来了,这里把_displayLink对象加入到主线程,然后调用render方法

再看一下之后调用的

- (void)addAnimation:(POPAnimation*)anim forObject:(id)obj key:(NSString*)key

{

//判断为空则返回

if(!anim || !obj) {

return;

}

// support arbitrarily many nil keys

if(!key) {

key = [[NSUUID UUID]UUIDString];

}

// lock

OSSpinLockLock(&_lock);

// get key, animation dict associated with object

// 把之前init方法中创建的_dict赋给keyAnimationDict

NSMutableDictionary*keyAnimationDict = (__bridgeid)CFDictionaryGetValue(_dict, (__bridgevoid*)obj);

// update associated animation state

if(nil== keyAnimationDict) {

//判断为空的情况下的处理

keyAnimationDict = [NSMutableDictionary dictionary];

CFDictionarySetValue(_dict, (__bridgevoid*)obj, (__bridgevoid*)keyAnimationDict);

}else{

// if the animation instance already exists, avoid cancelling only to restart

POPAnimation*existingAnim = keyAnimationDict[key];//根据所传入的key查找animation

if(existingAnim) {

// unlock

OSSpinLockUnlock(&_lock);

if(existingAnim == anim) {

//如果此查找到的existingAnim等于传入的anim则返回

return;

}

这里是应该防止,多个不同的animation公用一个key值

[selfremoveAnimationForObject:objkey:keycleanupDict:NO];

// lock

OSSpinLockLock(&_lock);

}

}

keyAnimationDict[key] = anim;

// create entry after potential removal

POPAnimatorItemRefitem(new POPAnimatorItem(obj, key, anim));

// add to list and pending list

_list.push_back(item);

_pendingList.push_back(item);

// support animation re-use, reset all animation state

POPAnimationGetState(anim)->reset(true);

// update display link

这个时候呢 根据方法实现给_displayLink.paused= NO;了 开始跑了

updateDisplayLink(self);

// unlock

OSSpinLockUnlock(&_lock);

// schedule runloop processing of pending animations

[self_scheduleProcess PendingList];

}

最后进入- (void)_scheduleProcessPendingList

- (void)_scheduleProcessPendingList

{

// see WebKit for magic numbers, eghttp://trac.webkit.org/changeset/166540

static const CFIndexCATransactionCommitRunLoopOrder =2000000;

static const CFIndexPOPAnimationApplyRunLoopOrder = CATransactionCommitRunLoopOrder -1;

// lock

OSSpinLockLock(&_lock);

if(!_pendingListObserver) {

__weakPOPAnimator*weakSelf =self;

//监听runloop

_pendingListObserver=CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault,kCFRunLoopBeforeWaiting|kCFRunLoopExit,false, POPAnimationApplyRunLoopOrder, ^(CFRunLoopObserverRefobserver,CFRunLoopActivityactivity) {

[weakSelf _processPendingList];//kCFRunLoopBeforeWaiting|kCFRunLoopExit下回调清除动画

});

if(_pendingListObserver) {

添加到主线程的runloop中

CFRunLoopAddObserver(CFRunLoopGetMain(),_pendingListObserver,kCFRunLoopCommonModes);

}

}

// unlock

OSSpinLockUnlock(&_lock);

}

然后呢_displaylink就开始调用rend方法进行动画了,就开始以1秒60次的频率刷新UI

整个过程就是这么一个过程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容