IOS 動畫例子(Path 菜單按鈕)


例子是我 從 code4app 上找的 是當時很火的 Path2 菜單按鈕  我現在來學習他

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章