旋转菜单

需要注意的是,设置动画values和fromValue的时候,设置的值代表的是基于最初状态的位置信息,而不是在当前的基础上面增加
自定类方法,这里是定义的xib
//
//  Menu.swift
//  滚动菜单
//
//  Created by admin on 16/1/28.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class Menu: UIView {

    @IBOutlet weak var rootMenu: UIButton!
    private var menus:[UIButton] = []
    private var menusX:[CGFloat] = []
    // 主菜单点击事件
    @IBAction func menuClick(sender: UIButton) {
        // 如果没有子菜单就结束执行
        if self.menus.first == nil
        {
            return
        }
        // 动画执行的时间
        let duration:CFTimeInterval = 3
        // 获得菜单动画信息
        let changeInfo = self.getChangeInfo()
        for var i = 0;i < self.menus.count;i++
        {
            // 初始化当前子菜单的动画组对象
            let animationGroup = CAAnimationGroup()
            // 设置时间
            animationGroup.duration = duration
            // 位移属性变化对象
            let positionX = CAKeyframeAnimation(keyPath: "position.x")
            positionX.values = changeInfo[0][i] as? [AnyObject]
            // 旋转属性赋值
            let rotation = CAKeyframeAnimation(keyPath: "transform.rotation")
            rotation.values = changeInfo[1][i] as? [AnyObject]
            // 把动画添加进组
            animationGroup.animations = [positionX,rotation]
            // 保持动画执行之后的状态
            animationGroup.removedOnCompletion = false
            animationGroup.fillMode = kCAFillModeForwards
            // 设置子菜单属性
            self.menus[i].center.x = changeInfo[0][i].lastObject as! CGFloat
            // 给当前控件添加动画
            self.menus[i].layer.addAnimation(animationGroup, forKey: nil)
        }
        // 主按钮动画效果
        let rootMenuRotation = CABasicAnimation(keyPath: "transform.rotation")
        // 开始位置
        rootMenuRotation.fromValue = (changeInfo[2] as! [CGFloat])[0]
        // 结束位置
        rootMenuRotation.toValue = (changeInfo[2] as! [CGFloat])[1]
        // 保持动画状态
        rootMenuRotation.removedOnCompletion = false
        rootMenuRotation.fillMode = kCAFillModeForwards
        // 时间
        rootMenuRotation.duration = duration
        // 添加动画
        self.rootMenu.layer.addAnimation(rootMenuRotation, forKey: nil)

    }
    // 获得菜单位置改变信息
    func getChangeInfo()->NSMutableArray
    {
        // 平移属性数组
        let transforms:NSMutableArray = []
        // 旋转属性数组
        let rotations:NSMutableArray = []
        // 主菜单按钮旋转属性数组
        var rootMenuRotation:[CGFloat] = []
        // 计算
        for var i = 0;i < self.menus.count;i++
        {
            if self.menus.first?.layer.position.x == self.rootMenu.center.x // 显示
            {
                // 注意这里的参数的含义不是增加这么多,而是在这几个节点的状态
                transforms.addObject([self.rootMenu.center.x,self.menusX[i] * 1.2,self.menusX[i]])
                rotations.addObject([0,M_PI * 4,M_PI * 2])
                rootMenuRotation = [0,CGFloat(M_PI * 0.25)]
            }
            else // 隐藏
            {
                transforms.addObject([self.menus[i].center.x,self.menus[i].center.x * 1.2,self.rootMenu.center.x])
                rotations.addObject([0,M_PI * 2,-M_PI * 2])
                rootMenuRotation = [CGFloat(M_PI * 0.25),0]
            }
        }
        return NSMutableArray(array: [transforms,rotations,rootMenuRotation])
    }
    // 添加子菜单方法,参数为图片名称
    func addMenu(name:String)
    {
        // 获得新添加的图片的名称
        let image = UIImage(imageLiteral: name)
        // 初始化当前子菜单按钮
        let button = UIButton(type: UIButtonType.Custom)
        // 设置图片
        button.setImage(image, forState: UIControlState.Normal)
        // 设置宽高
        button.bounds = CGRectMake(0, 0, 40, 40)
        // 添加进类属性
        self.menus.append(button)
        // 添加到父view
        self.addSubview(button)
        // 需要重新计算各个子菜单的位置,所以需要先置空之前的信息
        self.menusX = []
        // 获得magin
        let margin = ((self.frame.size.width * 0.8 - CGRectGetMaxX(self.rootMenu.frame)) - (CGFloat(self.menus.count) * button.bounds.size.width)) / CGFloat(self.menus.count)
        // 计算各个子控件的位置
        for var i = 0;i < self.menus.count;i++
        {
            // 获得主菜单按钮的中心点x轴坐标
            var preButtonX = self.rootMenu.center.x
            // 如果不是第一个,就获得上个控件的中心点x轴坐标
            if i != 0
            {
                preButtonX = self.menusX[i - 1]
            }
            // 初始化当前位置
            self.menus[i].center = self.rootMenu.center
            // 记录下button位置信息
            self.menusX.append(preButtonX + margin + button.bounds.size.width)
        }
        // 把主按钮设置在最上面显示
        self.bringSubviewToFront(self.rootMenu)
    }
}
控制器中的调用
//
//  ViewController.swift
//  滚动菜单
//
//  Created by admin on 16/1/28.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let menu = NSBundle.mainBundle().loadNibNamed("Menu", owner: nil, options: nil).last as! Menu
        menu.center.y = UIScreen.mainScreen().bounds.size.height * 0.5
        menu.addMenu("menu_btn_call")
        menu.addMenu("menu_btn_cheyou")
        menu.addMenu("menu_btn_tixing")
        self.view.addSubview(menu)
    }
}

标签: swift, 核心动画

添加新评论