pop架構(gòu)
由四大部分組成
1.Animations
2.Engine
3.Utility
4.WebCore
第一部分Animations
這一部分當(dāng)中定義了動(dòng)畫(huà)的類(lèi)型械拍,一共4種,分別是:
POPBasicAnimation ?? ? ? //基本動(dòng)畫(huà)固定時(shí)間間隔
POPCustomAnimation ? ?//自定義動(dòng)畫(huà)
POPDecayAnimation ? ? ?//帶阻尼動(dòng)畫(huà)效果
POPSpringAnimation ? ? //彈簧動(dòng)畫(huà)效果
各自有不同的使用場(chǎng)景
再看一下此目錄中的類(lèi)繼承的結(jié)構(gòu)關(guān)系
POPAnimation
———> POPPropertyAnimation
———>POPBasicAnimation
———>POPDecayAnimation
———>POPSpringAnimation
———>POPCustomAnimation
POPAnimation中定義了各種動(dòng)畫(huà)中需要的公有屬性
name beginTime tracer block 以及相應(yīng)的代理回調(diào),類(lèi)擴(kuò)展等等乾戏,以及引用了POPAnimationInternal中的私有結(jié)構(gòu)體等(_POPAnimationState)
basic動(dòng)畫(huà)示例
spring動(dòng)畫(huà)
想了下善玫,寫(xiě)這些東西網(wǎng)上隨便都能查的到啊洒敏,這樣還是看看源碼pop如何具體實(shí)現(xiàn)一個(gè)動(dòng)畫(huà)效果的,所以請(qǐng)拋開(kāi)上面所說(shuō)的Animations框架主題
先從一個(gè)最基本的basic動(dòng)畫(huà)的創(chuàng)建開(kāi)始
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"];
先看一下代碼的執(zhí)行流程
POPBasicAnimation *anBasic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionX];
然后進(jìn)入到這個(gè)方法
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.
/**
* 返回要進(jìn)行的動(dòng)畫(huà)屬性
*
*? @param aName ?屬性名稱(chēng)
*? @param aBlock
*
*? @return <#return value description#>
*/
+ (id)propertyWithName:(NSString*)aName initializer:(void(^)(POPMutableAnimatableProperty*prop))aBlock
{
POPAnimatableProperty*prop =nil;//聲明一個(gè)空的POPAnimatableProperty對(duì)象
staticNSMutableDictionary*_propertyDict =nil;
if(nil== _propertyDict) {
_propertyDict = [[NSMutableDictionary alloc]initWithCapacity:10];//實(shí)例化一個(gè)靜態(tài)可變字典
}
prop = _propertyDict[aName];
if(nil!= prop) {
returnprop;//如果prop不等于nil則返回prop
}
NSUIntegerstaticIdx =staticIndexWithName(aName);//如果prop為nil拿愧,則通過(guò)此函數(shù)定位下標(biāo)
if(NSNotFound!= staticIdx) {
//如果下標(biāo)不為NSNotFound,則新建一個(gè)POPStaticAnimatableProperty對(duì)象
POPStaticAnimatableProperty*staticProp = [[POPStaticAnimatableProperty alloc]init];
//讓新建對(duì)象的結(jié)構(gòu)體指向通過(guò)下標(biāo)根據(jù)結(jié)構(gòu)體數(shù)組找到的結(jié)構(gòu)體(語(yǔ)言組織有點(diǎn)問(wèn)題)
staticProp->_state= &_staticStates[staticIdx];
//添加字典中的key-value,key是aName碌尔,Value是POPStaticAnimatableProperty對(duì)象
_propertyDict[aName] = staticProp;
prop = staticProp;
}else if(NULL!= aBlock) {
//如果block參數(shù)不為空,則創(chuàng)建POPMutableAnimatableProperty對(duì)象
POPMutableAnimatableProperty*mutableProp =[[POPMutableAnimatableProperty alloc]init];
mutableProp.name= aName;
mutableProp.threshold=1.0;
aBlock(mutableProp);執(zhí)行block
prop = [mutableProp copy];
}
return prop;
}
接著
anBasic.toValue = @(testView.center.y+50);
執(zhí)行
- (void)setToValue:(id)aValue
{
POPPropertyAnimationState*s =__state;
VectorRefvec =POPUnbox(aValue, s->valueType, s->valueCount,YES);//解包一個(gè)向量浇辜,把point券敌,size ,rect柳洋,color對(duì)象轉(zhuǎn)換為vector
//vector的各種邏輯判斷
if(!vec_equal(vec, s->toVec)) {
s->toVec= vec;
// invalidate to dependent state
s->didReachToValue=false;
s->distanceVec=NULL;
if(s->tracing) {
//把動(dòng)畫(huà)過(guò)程中的屬性變化加入追蹤器待诅,生成event加入events數(shù)組中
[s->tracerupdateToValue:aValue];
}
// automatically unpause active animations
if(s->active&& s->paused) {
s->setPaused(false);
}
}
}
最后看一下
[testViewpop_addAnimation:anBasicforKey:@"position"];
是如何把一個(gè)animation加到view上一個(gè)動(dòng)畫(huà)就能夠動(dòng)起來(lái)
先看一下都調(diào)用了哪些方法
- (void)pop_addAnimation:(POPAnimation*)anim forKey:(NSString*)key
{
[[POPAnimator sharedAnimator]addAnimation:anim forObject:self key:key];
}
繼續(xù)...
+ (id)sharedAnimator
{
staticPOPAnimator* _animator =nil;
staticdispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
_animator = [[POPAnimator alloc] init];
});
return_animator;
}
繼續(xù)
- (id)init
{
self= [super init];
if(nil==self)return nil;
#if TARGET_OS_IPHONE
_displayLink= [CADisplayLink displayLinkWithTarget:self selector:@selector(render)];
//這個(gè)時(shí)候?yàn)閜ause狀態(tài)為yes動(dòng)畫(huà)還沒(méi)開(kāi)始跑
_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;
}
看見(jiàn)沒(méi)在這里創(chuàng)建了一個(gè)CADisplayLink對(duì)象(關(guān)于CADisplayLink是個(gè)什么東西,可以自行g(shù)oogle)
重點(diǎn)來(lái)了,這里把_displayLink對(duì)象加入到主線程熊镣,然后調(diào)用render方法
再看一下之后調(diào)用的
- (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方法中創(chuàng)建的_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];//根據(jù)所傳入的key查找animation
if(existingAnim) {
// unlock
OSSpinLockUnlock(&_lock);
if(existingAnim == anim) {
//如果此查找到的existingAnim等于傳入的anim則返回
return;
}
這里是應(yīng)該防止卑雁,多個(gè)不同的animation公用一個(gè)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
這個(gè)時(shí)候呢 根據(jù)方法實(shí)現(xiàn)給_displayLink.paused= NO;了 開(kāi)始跑了
updateDisplayLink(self);
// unlock
OSSpinLockUnlock(&_lock);
// schedule runloop processing of pending animations
[self_scheduleProcess PendingList];
}
最后進(jìn)入- (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;
//監(jiān)聽(tīng)runloop
_pendingListObserver=CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault,kCFRunLoopBeforeWaiting|kCFRunLoopExit,false, POPAnimationApplyRunLoopOrder, ^(CFRunLoopObserverRefobserver,CFRunLoopActivityactivity) {
[weakSelf _processPendingList];//kCFRunLoopBeforeWaiting|kCFRunLoopExit下回調(diào)清除動(dòng)畫(huà)
});
if(_pendingListObserver) {
添加到主線程的runloop中
CFRunLoopAddObserver(CFRunLoopGetMain(),_pendingListObserver,kCFRunLoopCommonModes);
}
}
// unlock
OSSpinLockUnlock(&_lock);
}
然后呢_displaylink就開(kāi)始調(diào)用rend方法進(jìn)行動(dòng)畫(huà)了,就開(kāi)始以1秒60次的頻率刷新UI
整個(gè)過(guò)程就是這么一個(gè)過(guò)程