2016年1月

核心动画CABasicAnimation

//
//  ViewController.swift
//  核心动画
//
//  Created by admin on 16/1/27.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        self.imageView.layer.contents = UIImage(imageLiteral: "3").CGImage

        // Do any additional setup after loading the view, typically from a nib.
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.scale()
    }
    // 缩放
    func scale()
    {
        // 这个属性
        let animation = CABasicAnimation()
        animation.keyPath = "transform.scale"
//        animation.toValue = NSValue.init(CATransform3D: CATransform3DMakeScale(1.5, 1.5, 1.5))
        animation.byValue = NSValue.init(CATransform3D: CATransform3DMakeScale(1.5, 1.5, 1.5))
//        self.imageView.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5)
        animation.removedOnCompletion  = false
        animation.fillMode = kCAFillModeForwards
        self.imageView.layer.addAnimation(animation, forKey: nil)
    }
    // 旋转
    func rotation()
    {
        // 这个属性
        let animation = CABasicAnimation()
        // 逐个修改
//        animation.keyPath = "transform.rotation.x"
//        animation.byValue = CGFloat(M_PI)
//        animation.removedOnCompletion = false
//        animation.fillMode = kCAFillModeForwards
        // 直接修改多个坐标
        animation.keyPath = "transform.rotation"
        self.imageView.layer.transform = CATransform3DMakeRotation(CGFloat(M_PI), 1, 1, 1)
        self.imageView.layer.addAnimation(animation, forKey: nil)
    }
    // 平移动画
    func translation()
    {
        let animation = CABasicAnimation()
        // 同时改变横向和纵向
        animation.keyPath = "transform.translation"
        // 从这个位置开始
//        animation.fromValue = NSValue.init(CGPoint: CGPointMake(10, 10))
        // 每次动画执行之后都会改变的距离
        animation.byValue = NSValue.init(CGPoint: CGPointMake(20, 20))
        // 在第一次执行动画的时候会发生偏移,然后无效了
//        animation.toValue = NSValue.init(CGPoint: CGPointMake(30, 30))
//        animation.keyPath = "transform.translation.x"
//        animation.byValue = 20
        animation.removedOnCompletion = false
        animation.fillMode = kCAFillModeForwards
        // 直接对属性进行赋值也是ok的
//        self.imageView.layer.transform = CATransform3DMakeTranslation(100, 100, 10)

        // 单独改变一个方向
        animation.keyPath = "transform.translation.x"
        animation.byValue = 10

        self.imageView.layer.addAnimation(animation, forKey: nil)
    }
    // bounds的动画效果
    func bounds()
    {
        // 实例化动画对象
        let animation = CABasicAnimation()
        // 设置监听的属性名
        animation.keyPath = "bounds"
        // 使用这个的话会有动画效果,并且动画执行完毕也不会回到原来的状态
        //        self.imageView.layer.bounds = CGRectMake(0, 0, 100, 100)
        // 使用这个会执行动画效果,但是结束之后会回到原来的状态,如果不希望恢复,需要设置下面两个属性
        animation.toValue = NSValue.init(CGRect: CGRectMake(0, 0, 100, 100))
        //        // 不设置下面两项的话动画执行完毕会回到原来的状态
        animation.removedOnCompletion = false
        animation.fillMode = kCAFillModeForwards
        animation.duration = 10
        // 给图层添加动画
        self.imageView.layer.addAnimation(animation, forKey: nil)
    }
}

图层(CALayer)的基本使用

//
//  ViewController.swift
//  图层_layer基本使用
//
//  Created by admin on 16/1/27.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!
    weak var childLayer:CALayer!
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置圆角的同时设置阴影,需要先将图片切成圆角,再设置阴影
        // self.imageView.layer.contents = self.corrnerImage().CGImage
        // self.transform(self.imageView.layer)
        // self.position()
        self.animation()
    }
    // 隐式动画,注意根层layer是没有隐式动画的
    func animation()
    {
        self.imageView.layer.contents = self.corrnerImage().CGImage
        let layer = CALayer()
        layer.frame = CGRectMake(100, 100, 100, 100)
        layer.contents = self.corrnerImage().CGImage
        self.imageView.layer.addSublayer(layer)
        // 给变量属性,方便之后使用
        self.childLayer = layer
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        CATransaction.begin()
        // 关闭子层的动画
//        CATransaction.setDisableActions(true)
        // 设置动画执行的时间
        CATransaction.setAnimationDuration(10)
        self.imageView.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5)
        self.childLayer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5)
        CATransaction.commit()
    }
    // 使用自定义layer
    func layer()
    {
        let layer = ViewController.MyLayer()
        layer.frame = CGRectMake(0, 0, 100, 100)
        self.view.layer.addSublayer(layer)
        // 和自定义view不同的是,自定义layer要显示,需要调用下 setNeedsDisplay 方法
        layer.setNeedsDisplay()
    }
    // 自定义layer
    class MyLayer: CALayer {
        // 渲染 layer 内容
        override func drawInContext(ctx: CGContext) {
            CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100))
            UIColor.redColor().set()
            CGContextFillPath(ctx)
        }
    }
    // position 和 anchorPoint
    func position()
    {
        let layer = CALayer()
        layer.frame = CGRectMake(0, 0, 100, 100)
        layer.backgroundColor = UIColor.blackColor().CGColor
        // 设置位置,这里的位置其实是设置锚点的坐标
        layer.position = CGPoint(x: 100, y: 100)
        // 设置锚点
        layer.anchorPoint = CGPoint(x: 0, y: 1)

        self.view.layer.addSublayer(layer)
    }
    // layer的形变属性
    func transform(layer:CALayer)
    {
        // 因为这里和之前的view的transform不一样,需要理解3d是什么样的,3d的有三个方向(正方体的一个角的三条棱可以作为参照),所以有三个坐标值,分别对应(x,y,z)
        // 平移,3d的有三个方向,所以有三个值,分别对应(x,y,z),注意这里最后一个是无效的
        layer.transform = CATransform3DMakeTranslation(10, 20, 0)
        // 缩放,最后一个属性无效
        layer.transform = CATransform3DMakeScale(1, 0.5, 10)
        // 旋转,参数分别对应(角度,x轴是否旋转,y轴是否旋转,z轴是否旋转)
        layer.transform = CATransform3DMakeRotation(CGFloat(M_PI * 0.3), 1, 1, 1)

        // kvc方式赋值,注意这里需要用 NSValue 转换下
        layer.setValue(NSValue.init(CATransform3D: CATransform3DMakeScale(1.5, 1, 0)), forKey: "transform")
        // kvc forKeyPath方式
        layer.setValue(1.1, forKeyPath: "transform.scale.x")
        // 不具体指定某个值
        layer.setValue(NSValue.init(CGPoint: CGPoint(x: 100, y: 10)), forKeyPath: "transform.translation")
    }
    // 获得圆角带边框图片
    func corrnerImage()->UIImage
    {
        let image = UIImage(imageLiteral: "3")
        UIGraphicsBeginImageContextWithOptions(image.size, false, 0)
        let layer = CALayer()
        layer.bounds = CGRectMake(0, 0, image.size.width, image.size.width)
        layer.contents = image.CGImage
        layer.cornerRadius = 10
        layer.masksToBounds = true
        layer.borderColor = UIColor.whiteColor().CGColor
        layer.borderWidth = 5
        layer.renderInContext(UIGraphicsGetCurrentContext()!)
        let resImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resImage
    }
    // 图层常用属性
    func layerAttr()
    {
        //        self.imageView.image = UIImage(imageLiteral: "2")
        // 使用了auto layout下面的设置是无效的
        self.imageView.layer.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, 300, 200)
        self.imageView.layer.bounds = CGRectMake(0, 0, 300, 200)
        // 圆角,两个属性一起使用才有效
        self.imageView.layer.cornerRadius = 10
        //        self.imageView.layer.masksToBounds = true
        // 设置图层背景颜色
        //        self.imageView.layer.backgroundColor = UIColor.redColor().CGColor
        // 设置layer背景,一般是个图片,
        self.imageView.layer.contents = UIImage(imageLiteral: "2").CGImage
        // 设置阴影,注意color和opacity要同时使用才能看到阴影,再就是,如果使用了剪切的话,阴影设置是无效的
        self.imageView.layer.shadowColor = UIColor.blackColor().CGColor
        // 阴影起始位置相对于原view的位置
        self.imageView.layer.shadowOffset = CGSize(width: 10, height: 10)
        // 阴影的透明度,默认是完全透明的
        self.imageView.layer.shadowOpacity = 0.5
        // 阴影的圆角
        self.imageView.layer.shadowRadius = 10
        // 边框,注意两个属性要配合使用才有效
        self.imageView.layer.borderColor = UIColor.whiteColor().CGColor
        self.imageView.layer.borderWidth = 5
    }
}

手势的基本使用

都是很简单的使用,唯一需要注意的就是,在手势过程中一些的值的属性是累加的,需要做一些的处理,还有,这里测试是用的一个 UIImageView,这个控件默认是不接受事件的,需要设置下

//
//  ViewController.swift
//  手势事件
//
//  Created by admin on 16/1/26.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController,UIGestureRecognizerDelegate {

    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        self.pan()
        // Do any additional setup after loading the view, typically from a nib.
    }
    // 拖拽事件
    func pan()
    {
        let pan = UIPanGestureRecognizer(target: self, action: "panFunc:")
        self.imageView.addGestureRecognizer(pan)
    }
    func panFunc(pan : UIPanGestureRecognizer)
    {
        self.imageView.center = CGPointMake(imageView.center.x + pan.translationInView(pan.view).x, imageView.center.y + pan.translationInView(pan.view).y)
        // 设置也是累加的,所以需要初始化下,不然特别快
        pan.setTranslation(CGPoint.zero, inView: pan.view)
    }
    // 同时响应两个事件
    // 允许响应多个事件,默认是只能响应一个事件的
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
    func gustures()
    {
        let rotation = UIRotationGestureRecognizer(target: self, action: "rotationFunc:")
        // 注意设置代理,只需要设置一个就ok了
        rotation.delegate = self
        self.imageView.addGestureRecognizer(rotation)
        let pinch = UIPinchGestureRecognizer(target: self, action: "pinchFunc:")
        self.imageView.addGestureRecognizer(pinch)
    }
    // 旋转事件
    func rotation()
    {
        let rotation = UIRotationGestureRecognizer(target: self, action: "rotationFunc:")
        self.imageView.addGestureRecognizer(rotation)
    }
    func rotationFunc(rotation:UIRotationGestureRecognizer)
    {
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation.rotation)
        // 这里也是一个累加的值,所以需要设置下,不然特别快
        rotation.rotation = 0
    }
    // 捏合事件
    func pinch()
    {
        // 实例化对象
        let pinch = UIPinchGestureRecognizer(target: self, action: "pinchFunc:")
        // 添加到控件
        self.imageView.addGestureRecognizer(pinch)
    }
    func pinchFunc(pinch:UIPinchGestureRecognizer)
    {
        self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale)
        // 注意这里重新赋值1了,因为这里的值是一个累加的值,不设置的话会特别快
        pinch.scale = 1
    }
    // 扫事件
    func swip()
    {
        // 创建对象并绑定目标
        let swip = UISwipeGestureRecognizer(target: self, action: "swipFunc:")
        // 响应的方向,是这个方向才会响应
        swip.direction = UISwipeGestureRecognizerDirection.Down
        // 添加事件到控件
        self.imageView.addGestureRecognizer(swip)
    }
    // 事件响应的函数
    func swipFunc(swip:UISwipeGestureRecognizer)
    {
        print(swip.state)
    }
    // 长按事件
    func long()
    {
        // 实例化事件对象
        let long = UILongPressGestureRecognizer()
        // 添加手势到控件
        self.imageView.addGestureRecognizer(long)
        // 设置属性
        // 按的时间到达设置的这个值之后才响应事件
        long.minimumPressDuration = 1
        // 允许移动的范围
        long.allowableMovement = 1
        // 设置代理
        long.delegate = self
        // 添加手势监听的方法
        long.addTarget(self, action: "longFunc:")
    }
    func longFunc(long:UILongPressGestureRecognizer)
    {
        if long.state == UIGestureRecognizerState.Began
        {
            print("开始")
        }
        else if long.state == UIGestureRecognizerState.Ended
        {
            print("结束")
        }
    }
    // 敲击事件
    func tab()
    {
        // 实例化事件对象
        let tab = UITapGestureRecognizer()
        // 点击的次数,达到这个次数才会响应
        tab.numberOfTapsRequired = 2
        // 设置代理
        tab.delegate = self
        // 把手势添加到view上
        self.imageView.addGestureRecognizer(tab)
        // 添加监听的方法
        tab.addTarget(self, action: "tabFunc:")
    }
    // 触摸响应的方法
    func tabFunc(tab:UITapGestureRecognizer)
    {
        print(tab)
    }
    // 是否接受触摸事件
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        return true
    }
}

swift简易画板

控制器类
//
//  ViewController.swift
//  简易画板
//
//  Created by admin on 16/1/25.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var drawingBoard: DrawingBoard!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    @IBAction func back(sender: AnyObject) {
        self.drawingBoard.back()
    }
    @IBAction func clear(sender: AnyObject) {
        self.drawingBoard.clear()
    }
    @IBAction func save(sender: AnyObject) {
        self.drawingBoard.save()
    }
    @IBAction func selectColor(sender: UIButton) {
        self.drawingBoard.selectColor(sender.backgroundColor!)
    }
}
画板类
//
//  DrawingBoard.swift
//  简易画板
//
//  Created by admin on 16/1/25.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit
// 线结构体
struct Line {
    let color:UIColor
    var points:[CGPoint] = []
}
// 画板类,使用上下文方式画
class DrawingBoard: UIView {
    // 线的集合
    var lines:[Line] = []
    // 当前选择的颜色
    var lineColor:UIColor = UIColor.blackColor()
    // 开始触摸方法,在开始触摸的时候新初始化一个线结构体
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let tempLine = Line(color: self.lineColor, points: [])
        lines.append(tempLine)
    }
    // 移动的时候给当前的线结构体添加点
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = (touches as NSSet).anyObject()
        // 添加当前线的结构体到线集合数组
        lines[self.lines.count - 1].points.append((touch?.locationInView(touch?.view))!)
        self.setNeedsDisplay()
    }
    // 画
    override func drawRect(rect: CGRect) {
        // 先获取上下文,在添加点
        let context = UIGraphicsGetCurrentContext()
        // 设置线的样式
        CGContextSetLineCap(context, CGLineCap.Round)
        CGContextSetLineJoin(context, CGLineJoin.Round)
        CGContextSetLineWidth(context, 10)
        for var j = 0;j < self.lines.count;j++
        {
            self.lines[j].color.set()
            for var i = 0;i < self.lines[j].points.count;i++
            {
                let point:CGPoint = (self.lines[j].points[i])
                if i == 0
                {
                    CGContextMoveToPoint(context, point.x, point.y)
                }
                else
                {
                    CGContextAddLineToPoint(context, point.x, point.y)
                }
            }
            CGContextStrokePath(context)
        }
    }
    // 回退
    func back()
    {
        if self.lines.count > 0
        {
            self.lines.removeLast()
            self.setNeedsDisplay()
        }
    }
    // 清屏
    func clear()
    {
        self.lines = []
        self.setNeedsDisplay()
    }
    // 保存颜色
    func save()
    {
        // 开始位图上下文
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0)
        // 画图
        self.setNeedsDisplay()
        // 获取当前图片
        let context = UIGraphicsGetCurrentContext()
        self.layer.renderInContext(context!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        // 转换成 NSData 数据
        let resImage = UIImagePNGRepresentation(image)
        // 保存
        resImage?.writeToFile("/Users/admin/Desktop/DrawingBoard.png", atomically: true)
    }
    // 
    func selectColor(color:UIColor)
    {
        self.lineColor = color
    }
}
画板类,UIBezierPath方式画
//
//  DrawBoardBezierPath.swift
//  简易画板
//
//  Created by admin on 16/1/25.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit
// 线结构体,为了和之前的区分,这里的名字有点长
struct LineBezierPath {
    let color:UIColor
    var points:UIBezierPath
}
// 画板类,这个使用BezierPath画
class DrawBoardBezierPath: UIView {
    var lines:[LineBezierPath] = []
    // 当前选择的颜色
    var lineColor:UIColor = UIColor.blackColor()
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = (touches as NSSet).anyObject()
        // 初始化 UIBezierPath 对象
        let bezierPath = UIBezierPath()
        // 设置线的开始点
        bezierPath.moveToPoint((touch?.locationInView(touch?.view))!)
        // 初始化线的结构体
        let line = LineBezierPath(color: self.lineColor, points: bezierPath)
        // 添加线到线集合
        self.lines.append(line)
    }
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = (touches as NSSet).anyObject()
        // 给当前的线添加点
        self.lines.last?.points.addLineToPoint((touch?.locationInView(touch?.view))!)
        self.setNeedsDisplay()
    }
    override func drawRect(rect: CGRect) {
        // 画
        for var i = 0;i < self.lines.count;i++
        {
            self.lines[i].points.lineCapStyle = CGLineCap.Round
            self.lines[i].points.lineJoinStyle = CGLineJoin.Round
            self.lines[i].points.lineWidth = 10
            self.lines[i].color.set()
            self.lines[i].points.stroke()
        }
    }
    // 回退
    func back()
    {
        if self.lines.count > 0
        {
            self.lines.removeLast()
            self.setNeedsDisplay()
        }
    }
    // 清屏
    func clear()
    {
        self.lines = []
        self.setNeedsDisplay()
    }
    // 保存颜色
    func save()
    {
        // 开始位图上下文
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0)
        // 画图
        self.setNeedsDisplay()
        // 获取当前图片
        let context = UIGraphicsGetCurrentContext()
        self.layer.renderInContext(context!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        // 转换成 NSData 数据
        let resImage = UIImagePNGRepresentation(image)
        // 保存
        resImage?.writeToFile("/Users/admin/Desktop/DrawingBoard.png", atomically: true)
    }
    //
    func selectColor(color:UIColor)
    {
        self.lineColor = color
    }
}

触摸事件初步使用

//
//  ViewController.swift
//  触摸事件
//
//  Created by admin on 16/1/25.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    // 触摸开始
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        // 获取touch对象
        let touch = (touches as NSSet).anyObject()
        // 获取当前点击的位置,位置坐标是相对于当前传入的view,如果传入nil就是想对于整个窗口
        print(touch!.locationInView(touch!.view))
        // 获取连续点击的次数
        print(touch!.tapCount)
    }
    // 触摸移动
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = (touches as NSSet).anyObject()
        print("移动前的坐标\(touch?.previousLocationInView(touch?.view))")
        print("移动后的坐标\(touch?.locationInView(touch?.view))")
        print("==============")
        // 拖动view的时候改变view的位置
        let point = ((touch?.view)! as UIView).center
        ((touch?.view)! as UIView).center = CGPointMake(point.x + ((touch?.locationInView(touch?.view).x)! - (touch?.previousLocationInView(touch?.view).x)!), point.y + ((touch?.locationInView(touch?.view).y)! - (touch?.previousLocationInView(touch?.view).y)!))
    }
    // 触摸结束
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

    }
    // 终止触摸,譬如被打电话提前结束
    override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {

    }
    override func touchesEstimatedPropertiesUpdated(touches: Set<NSObject>) {

    }
}