http://code4app.com/ios/QuadCurve-Menu/4f67ef546803fa6d45000000
當你下載完打開是這樣的
我們是來學習他那動畫效果的 所以我們要開的 核心文件就 一個
QuadCurveMenu
打開 QuadCurveMenu.m 文件 看 初始方法
QuadCurveMenuItem *item = [_menusArray objectAtIndex:i];
item.tag = 1000 + i;
item.startPoint = STARTPOINT; //開始座標
//最終停留的座標
item.endPoint = CGPointMake(STARTPOINT.x + ENDRADIUS * cosf(i * M_PI_2 / (count - 1)), STARTPOINT.y - ENDRADIUS * sinf(i * M_PI_2 / (count - 1)));
//靠近停留座標的位置
item.nearPoint = CGPointMake(STARTPOINT.x + NEARRADIUS * cosf(i * M_PI_2 / (count - 1)), STARTPOINT.y - NEARRADIUS * sinf(i * M_PI_2 / (count - 1)));
//超過 停留座標的位置 這些座標用來做 物體 慣性的 使得動畫看起來更自然也更美觀
item.farPoint = CGPointMake(STARTPOINT.x + FARRADIUS * cosf(i * M_PI_2 / (count - 1)), STARTPOINT.y - FARRADIUS * sinf(i * M_PI_2 / (count - 1)));
/*
座標算法就是 圓的極座標方程
x = a+r*cos(@)
y = b+r*sin(@)
因爲該動畫 是從上到下的 把 cos 和 sin 換了個位置 有興趣的 可以把他們換回來 看看效果
*/
item.center = item.startPoint;
item.delegate = self;
[self addSubview:item];
這個只是 算座標的方法
下面 我們看他的動畫是怎麼設計的
當你點擊了 AddButton
- (void)quadCurveMenuItemTouchesBegan:(QuadCurveMenuItem *)item
{
if (item == _addButton)
{
self.expanding = !self.isExpanding;
}
}
好我們在看
- (void)setExpanding:(BOOL)expanding
{
_expanding = expanding;
// rotate add button
float angle = self.isExpanding ? -M_PI_4 : 0.0f;
[UIView animateWithDuration:0.2f animations:^{
//把 AddButton 按鈕旋轉 angle 度。
//這個是 矩陣變換 看名字大家應該就知道做什麼用的了
// Creating an Affine Transformation Matrix
// CGAffineTransformMake //這個最牛 想要什麼自己弄 可惜水平不夠 只會用下面的方法
// CGAffineTransformMakeRotation
// CGAffineTransformMakeScale
// CGAffineTransformMakeTranslation
_addButton.transform = CGAffineTransformMakeRotation(angle);
}];
// expand or close animation
if (!_timer)
{
_flag = self.isExpanding ? 0 : 5;
//真正的動畫還是 藏在 _expand 和 _close 裏面
SEL selector = self.isExpanding ? @selector(_expand) : @selector(_close);
//對每一個 Item 做延遲處理 做時差效果
_timer = [[NSTimer scheduledTimerWithTimeInterval:TIMEOFFSET target:self selector:selector userInfo:nil repeats:YES] retain];
}
}
看下 _expand 方法
- (void)_expand
{
if (_flag == 6) //這邊設死了 固定6個Item 可自行更改
{
[_timer invalidate];
[_timer release];
_timer = nil;
return;
}
int tag = 1000 + _flag;
QuadCurveMenuItem *item = (QuadCurveMenuItem *)[self viewWithTag:tag];
//按 Z 軸旋轉 可以改成 x,y 改成什麼 就是按什麼軸旋轉 大家可以自己 改改看效果
CAKeyframeAnimation *rotateAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
//關鍵幀 就是賦值 跟 keyTimes 配合
rotateAnimation.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:M_PI],[NSNumber numberWithFloat:0.0f], nil];
//動畫時間
rotateAnimation.duration = 0.5f;
//跟關鍵幀配合
rotateAnimation.keyTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:.3],
[NSNumber numberWithFloat:.4], nil];
//路線的動畫
CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
positionAnimation.duration = 0.5f;
CGMutablePathRef path = CGPathCreateMutable();
//移動到開始座標
CGPathMoveToPoint(path, NULL, item.startPoint.x, item.startPoint.y);
//添加路勁座標點 先移動到 靠近位置
CGPathAddLineToPoint(path, NULL, item.farPoint.x, item.farPoint.y);
//移動到 超出位置 看起來有反彈效果
CGPathAddLineToPoint(path, NULL, item.nearPoint.x, item.nearPoint.y);
//最終的座標
CGPathAddLineToPoint(path, NULL, item.endPoint.x, item.endPoint.y);
positionAnimation.path = path;
CGPathRelease(path);
CAAnimationGroup *animationgroup = [CAAnimationGroup animation];
animationgroup.animations = [NSArray arrayWithObjects:positionAnimation, rotateAnimation, nil];
animationgroup.duration = 0.5f;
animationgroup.fillMode = kCAFillModeForwards;
//EaseIn 前端慢 EaseInEaseOut 兩端慢 中間快 EaseOut 後端慢
animationgroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[item.layer addAnimation:animationgroup forKey:@"Expand"];
item.center = item.endPoint;
_flag ++; // 下一個Item
}
_close
的做法 跟_expand 差不多就不說了在點擊了 Item 按鈕後 會有個 Item 放大 其他按鈕縮小的動畫
- (CAAnimationGroup *)_blowupAnimationAtPoint:(CGPoint)p
{
//位置保持不變
CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
positionAnimation.values = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:p], nil];
positionAnimation.keyTimes = [NSArray arrayWithObjects: [NSNumber numberWithFloat:.3], nil];
//放大3倍
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3, 3, 1)];
//透明
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.0f];
CAAnimationGroup *animationgroup = [CAAnimationGroup animation];
animationgroup.animations = [NSArray arrayWithObjects:positionAnimation, scaleAnimation, opacityAnimation, nil];
animationgroup.duration = 0.3f;
animationgroup.fillMode = kCAFillModeForwards;
return animationgroup;
}
縮小跟這寫法 差不多 大家自己看
感覺我就是在註釋!
曹操。。
教新手個 實用的 如果你要 改變 這控件的位置這麼辦呢?
如果你要改成 右上角 像這樣
你只要改
把
#define STARTPOINT CGPointMake(50, 430)
改成#define STARTPOINT CGPointMake(270, 50)
接下來是 位置 位置 簡單 只要更改下 + - 號就行了
//最終停留的座標
item.endPoint = CGPointMake(STARTPOINT.x - ENDRADIUS * cosf(i * M_PI_2 / (count - 1)), STARTPOINT.y + ENDRADIUS * sinf(i * M_PI_2 / (count - 1)));
//靠近停留座標的位置
item.nearPoint = CGPointMake(STARTPOINT.x - NEARRADIUS * cosf(i * M_PI_2 / (count - 1)), STARTPOINT.y + NEARRADIUS * sinf(i * M_PI_2 / (count - 1)));
//超過 停留座標的位置 這些座標用來做 物體 慣性的 使得動畫看起來更自然也更美觀
item.farPoint = CGPointMake(STARTPOINT.x - FARRADIUS * cosf(i * M_PI_2 / (count - 1)), STARTPOINT.y + FARRADIUS * sinf(i * M_PI_2 / (count - 1)));
OVER