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