用CAShapeLayer 实现打钩动画轨迹效果

####首先对CAShapeLayer的了解
CAShapeLayer相关的动画知识.

普通CALayer在被初始化时是需要给一个frame值的,这个frame值一般都与给定view的bounds值一致,它本身是有形状的,而且是矩形.

CAShapeLayer在初始化时也需要给一个frame值,但是,它本身没有形状,它的形状来源于你给定的一个path,然后它去取CGPath值,它与CALayer有着很大的区别
CAShapeLayer有着几点很重要:

  1. 它依附于一个给定的path,必须给与path,而且,即使path不完整也会自动首尾相接

  2. strokeStart以及strokeEnd代表着在这个path中所占用的百分比

  3. CAShapeLayer动画仅仅限于沿着边缘的动画效果,它实现不了填充效果

####实现打钩效果
image

image

class CheckControl: UIControl {

//线的宽度
var lineWith:CGFloat = 2.0
//颜色
var lineColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1.000)
//是否有外圆边框
var isRoundBorder :Bool = true

lazy var lineLayer:CAShapeLayer = {
    let ret = CAShapeLayer()
    ret.strokeColor = self.lineColor.CGColor;
    ret.fillColor = UIColor.clearColor().CGColor;
    ret.lineCap = kCALineCapRound;
    ret.lineJoin = kCALineJoinRound;
    ret.lineWidth = self.lineWith;
    ret.path = self.checkmarkPath().CGPath;
    return ret;

}()
func check(){
    //lineLayer = self.checkmarkLayerWithColor()
    self.layer.addSublayer(self.lineLayer)
    lineLayer.strokeStart = 0;
    lineLayer.strokeEnd = 0;
    CATransaction.begin()
    CATransaction.setCompletionBlock {
        self.lineLayer.strokeStart = 0.0;
        self.lineLayer.strokeEnd = 1.0;
    }

    CATransaction.commit()
}
func dissmiss(){

    CATransaction.begin();
    CATransaction.setCompletionBlock {
        self.lineLayer.strokeStart = 0.0;
        self.lineLayer.strokeEnd = 0.0;
    }

    CATransaction.commit();
}

/**
 可以画的有效区域

 - returns: CGRect
 */
func insetRect() ->CGRect{
    var ret = self.bounds
    ret = CGRectInset(ret, 2 * lineWith , 2 * lineWith)
    return ret
}
/**
 外切圆半径

 - returns: CGFloat
 */
func outerRadius() ->CGFloat{

    return sqrt(pow(self.insetRect().size.width, 2) + pow(self.insetRect().size.height, 2)) / 2;
}
/**
    内切圆半径
 - returns: CGFloat
 */
func innerRadius() -> CGFloat{
    return min(self.insetRect().size.width, self.insetRect().size.height) / 2
}
/**
 获取中心即圆心

 - returns: CGPoint
 */
func bounsCenter() -> CGPoint{

    return CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2)
}



/**
 钩号起始点

 - returns: CGPoint
 */
func startPoint() -> CGPoint{
    let angle:Double = 13 * M_PI / 12
    return CGPointMake(self.bounsCenter().x + self.innerRadius() * CGFloat(cos(angle)),self.bounsCenter().y + self.innerRadius() * CGFloat(sin(angle)))
}
/**
 钩号中间转折点

 - returns: CGPoint
 */
func middlePoint() -> CGPoint {
    return CGPointMake(self.bounsCenter().x - self.innerRadius() * 0.25, self.bounsCenter().y + self.innerRadius() * 0.8)
}
/**
 钩号终止点

 - returns: CGPoint
 */
func endPoint() -> CGPoint {
    let  angle: Double = 3*M_PI/2 + M_PI*3/10
    return CGPointMake(self.bounsCenter().x + self.outerRadius() * CGFloat(cos(angle)), self.bounsCenter().y + self.outerRadius() * CGFloat(sin(angle)));
}
func checkmarkPath()-> UIBezierPath{
    let  path = UIBezierPath()
    path.moveToPoint(self.startPoint())
    path.addLineToPoint(self.middlePoint())
    path.addLineToPoint(self.endPoint())
    if self.isRoundBorder{
        let  angle: Double = 3*M_PI/2 + M_PI*3/10
        path.addArcWithCenter(self.bounsCenter(), radius: self.outerRadius(), startAngle:CGFloat(angle) , endAngle: CGFloat(2*M_PI)+CGFloat(angle), clockwise: true)
    }
    return path;



}


}

代码地址https://github.com/menhui222/CheckControl

最近的文章

ios自带Emotion表情

##iOS 自定义emoji表情键盘 ####首先 ,想要获取系统的表情,要首先知道表情对应的UTF8 的编码方式 //将数字转为 func EMOJI_CODE_TO_SYMBOL(x:Int)-> Int { return ((((0x808080F0 | (x &am …

于 继续阅读
更早的文章

用AVFoundation实现二维码扫描

首先对AVFoundation的了解(指我的了解因为我能力有限所以可能有不到位的地方)AVFoundation是一个可以用来使用和创建基于时间的视听媒体的框架,例如:您可以用它来检查,创建,编辑或是重新编码媒体文件。也可以从设备中获取输入流,在视频实时播放时操作和回放。下图时AVFoundation …

于 继续阅读