登录 立即注册
金钱:

Code4App-iOS开发-iOS 开源代码库-iOS代码实例搜索-iOS特效示例-iOS代码例子下载-Code4App.com

MBMotion 弹性动画弹出菜单特效

[复制链接]
来自: 李世铿 分类: iOS精品源码 上传时间: 2016-4-25 12:58:09
Tag:animation 设计效果 private drawing custom

项目介绍:

文:mmoaay/MBMotion
实现的弹性动画弹出菜单特效,正在不断丰富中… 目前实现的效果列表
  • MBMotionActionSheet
    设计效果如下:


    主要代码示例:

[Objective-C] 查看源文件 复制代码
import UIKit

class MBMotionActionSheet: NSObject {
    
    private var backgroundLayer = CAShapeLayer()
    
    @IBOutlet var bkgroundView: UIView!
    @IBOutlet var motionView: UIView!
    
    @IBOutlet weak var contentView: UIView!
    
    private weak var containerView: UIView?
    
    var isExpanded:Bool = false
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
    // Drawing code
    }
    */
    
    init(containerView: UIView!, contentView: UIView!) {        
        super.init()
        
        self.containerView = containerView
        
        NSBundle.mainBundle().loadNibNamed("MBMotionActionSheet", owner: self, options: nil)
        
        self.contentView.addSubview(contentView)
        contentView.snp_makeConstraints { (make) -> Void in
            make.leading.bottom.trailing.equalTo(self.contentView)
            make.top.equalTo(self.contentView.snp_top).offset(44.0)
        }
        
        self.addActionSheet()
    }
    
    private func animatedWithMotionView(height:Float, duration:NSTimeInterval ,options:UIViewAnimationOptions) {
        self.motionView.snp_updateConstraints { (make) -> Void in
            make.height.equalTo(height)
        }
        UIView.animateWithDuration(duration, delay: 0.0, options: options, animations: { () -> Void in
            UIApplication.sharedApplication().keyWindow?.layoutIfNeeded()
            }, completion: nil)
    }
    
    private func animtedWithRipples(fromValue:Float, toValue:Float, duration:NSTimeInterval){
        let animation = CAKeyframeAnimation(keyPath: "path")
        
        animation.duration = duration
        animation.fillMode = kCAFillModeForwards
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        var pathValues = Array<CGPathRef>()
        for(var i = 0; i <= Int(duration * 60); i++){
            pathValues.append(getRipplesPath(Float(Float(i) / (Float(duration) * 60)), fromValue:fromValue, toValue:toValue))
        }
        
        animation.values = pathValues
        animation.autoreverses = false
        animation.removedOnCompletion = false
        animation.delegate = self
        backgroundLayer.path = getRipplesPath(1, fromValue:fromValue, toValue:toValue)
        
        backgroundLayer.addAnimation(animation, forKey: "ripples")
    }
    
    private func getRipplesPath(progress:Float, fromValue:Float, toValue:Float) -> CGPathRef{
        let valuePorgress = CGFloat((toValue-fromValue) * progress)
        let path = UIBezierPath()
        
        
        let controlPointTop = CGPointMake(self.contentView.width * 0.5, (CGFloat(fromValue)+valuePorgress))
        path.moveToPoint(CGPointMake(0, 44))
        path.addQuadCurveToPoint(CGPointMake(self.contentView.width, 44), controlPoint: controlPointTop)
        path.addLineToPoint(CGPointMake(self.contentView.width, self.contentView.height))
        path.addLineToPoint(CGPointMake(0, self.contentView.height))
        path.addLineToPoint(CGPointMake(0, 44))
        
        return path.CGPath
    }
    
    private func animtedWithContainerView(sx:CGFloat,sy:CGFloat,sz:CGFloat, duration:NSTimeInterval) {
        UIView.animateWithDuration(duration) { () -> Void in
            self.containerView?.layer.transform = CATransform3DMakeScale(sx, sy, sz)
        }
    }
    
    private func animatedWithStatusBar (style:UIStatusBarStyle, duration:NSTimeInterval) {
        if let _ = self.containerView {
            UIApplication.sharedApplication().setStatusBarStyle(style, animated: true)
        }
    }
    
    private func animtedWithBkGround(opacity:Float, duration:NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.bkgroundView.layer.opacity = opacity
            }) { (Bool) -> Void in
                if 0.0 == opacity {
                    self.bkgroundView.userInteractionEnabled = false
                } else {
                    self.bkgroundView.userInteractionEnabled = true
                }
        }
    }
    
    private func addActionSheet() {
        UIApplication.sharedApplication().keyWindow?.addSubview(self.bkgroundView)
        self.bkgroundView.snp_remakeConstraints { (make) -> Void in
            make.edges.equalTo(UIApplication.sharedApplication().keyWindow!)
        }
        
        UIApplication.sharedApplication().keyWindow?.addSubview(self.motionView)
        self.motionView.snp_remakeConstraints { (make) -> Void in
            make.height.equalTo(44.0+49.0)
            make.leading.trailing.equalTo(UIApplication.sharedApplication().keyWindow!)
            make.bottom.equalTo(UIApplication.sharedApplication().keyWindow!)
        }
        
        UIApplication.sharedApplication().keyWindow?.layoutIfNeeded()
        
        backgroundLayer.fillColor = self.contentView.backgroundColor?.CGColor
        let path = UIBezierPath()
        path.moveToPoint(CGPointMake(0, 44.0))
        path.addLineToPoint(CGPointMake(self.contentView.width, 44.0))
        path.addLineToPoint(CGPointMake(self.contentView.width, self.contentView.height))
        path.addLineToPoint(CGPointMake(0, self.contentView.height))
        path.addLineToPoint(CGPointMake(0, 44.0))
        backgroundLayer.strokeColor = UIColor.clearColor().CGColor
        backgroundLayer.path = path.CGPath
        backgroundLayer.frame = self.contentView.layer.bounds
        
        self.contentView.layer.mask = backgroundLayer
        self.contentView.layer.masksToBounds = true
    }
    
    func removeActionSheet() {
        self.motionView.removeFromSuperview()
        self.bkgroundView.removeFromSuperview()
    }
    
    func expandActionSheet() {
        if !self.isExpanded {
            self.animtedWithBkGround(0.4, duration: 0.8)
            self.animatedWithStatusBar(UIStatusBarStyle.LightContent,duration: 0.8)
            
            self.animtedWithRipples(44.0, toValue: 0.0, duration: 0.3)
            self.animtedWithContainerView(1.02, sy: 1.02, sz: 1.02, duration: 0.3)
            
            
            MBTimeUtil.executeAfterDelay(0.3, clurse: {
                self.animatedWithMotionView(Float(UIScreen.mainScreen().bounds.size.height)-25.0, duration: 0.3, options: UIViewAnimationOptions.CurveEaseIn)
                self.animtedWithRipples(0.0, toValue: 54.0, duration: 0.3)
                
                self.animtedWithContainerView(0.89, sy: 0.89, sz: 0.89, duration: 0.4)
            })
            
            MBTimeUtil.executeAfterDelay(0.6, clurse: { () -> Void in
                self.animtedWithRipples(54.0, toValue: 34.0, duration: 0.1)
            })
            
            MBTimeUtil.executeAfterDelay(0.7, clurse: { () -> Void in
                self.animtedWithRipples(34.0, toValue: 44.0, duration: 0.1)
                self.animtedWithContainerView(0.9, sy: 0.9, sz: 0.9, duration: 0.1)
            })
            
            MBTimeUtil.executeAfterDelay(0.8, clurse: { () -> Void in
                self.isExpanded = true
            })
        }
    }
    
    func collapseActionSheet() {
        if self.isExpanded {
            self.animtedWithBkGround(0.0, duration: 0.8)
            self.animatedWithStatusBar(UIStatusBarStyle.Default,duration: 0.8)
            self.animtedWithRipples(44.0, toValue: 34.0, duration: 0.1)
            self.animtedWithContainerView(0.89, sy: 0.89, sz: 0.89, duration: 0.1)
            
            MBTimeUtil.executeAfterDelay(0.1, clurse: { () -> Void in
                self.animtedWithRipples(34.0, toValue: 54.0, duration: 0.1)
                self.animtedWithContainerView(1.02, sy: 1.02, sz: 1.02, duration: 0.4)
            })
            
            MBTimeUtil.executeAfterDelay(0.2, clurse: {
                self.animtedWithRipples(54.0, toValue: 0.0, duration: 0.3)
                self.animatedWithMotionView(44.0+49.0, duration: 0.3, options: UIViewAnimationOptions.CurveEaseOut)
            })
            
            MBTimeUtil.executeAfterDelay(0.5, clurse: {
                self.animtedWithRipples(0.0, toValue: 44.0, duration: 0.3)
                self.animtedWithContainerView(1, sy: 1, sz: 1, duration: 0.3)
            })
            
            MBTimeUtil.executeAfterDelay(0.8, clurse: { () -> Void in
                self.isExpanded = false
            })
        }
    }
}




相关源码推荐:

我来说两句
*滑动验证:
所有评论(101)
lijian0119 2016-4-25 13:24:34
楼主用心了,内容非常精彩。
回复
wanghe826 2016-4-25 13:42:42
感谢分享,Code4App有你更精彩:)
回复
wings0728 2016-4-25 14:15:18
楼主威武啊,Code4App有你更给力!
回复
ztpz0563 2016-4-25 14:29:32
感谢分享,Code4App有你更精彩:)
回复
春风动人 2016-4-25 14:53:18
虽不明,但觉厉!
回复
carter300 2016-4-25 16:05:28
正需要啊,感谢楼主无私分享!
回复
张濛 2016-4-25 16:42:10
学习学习!
回复
张濛 2016-4-25 16:43:01
感谢分享,Code4App有你更精彩
回复
yzy_fishyy 2016-4-25 17:03:30
淡定,淡定,淡定……
回复
提取码:  下载次数:110 状态:已购或VIP 售价:0(原价:5)金钱 下载权限:初级码农 
3336 0 110
联系我们
首页/微信公众账号投稿

帖子代码编辑/版权问题

QQ:435399051,742864542

如何获得代码达人称号?

代码贡献英雄榜
用户名 下载数
通过邮件订阅最新 Code4App 信息
上一条 /4 下一条
联系我们
关闭
合作电话:
13802416937
Email:
435399051@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| Github|申请友链|手机版|Code4App ( 粤ICP备15117877号-1 )

快速回复 返回顶部 返回列表