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