• - 通过 UIBezierPath 做一个中空的扫描器


    今天在公司的代码里看到通过 UIBezierPath 绘制 CALayer 然后实现中空的正方形,感觉还挺有意思的,简单记录一下 UIBezierPath 这个东西。

    一条线

    我们自定义一个 BezierView 继承自 UIView ,并重写它的 drawRect 方法实现绘图操作。

    import UIKit
    
    class BezierView: UIView {
        override func drawRect(rect: CGRect) {
            super.drawRect(rect);
            var myBezier = UIBezierPath()
            myBezier.moveToPoint(CGPoint(x: 100, y: 100))
            myBezier.addLineToPoint(CGPoint(x: 200, y: 100))
            UIColor.orangeColor().setStroke()
            myBezier.stroke()
        }
    }
    

    两条线

    也就是先 moveToPoint 然后再 addLineToPoint 一次:

    import UIKit
    
    class BezierView: UIView {
        override func drawRect(rect: CGRect) {
            super.drawRect(rect);
            var myBezier = UIBezierPath()
            myBezier.moveToPoint(CGPoint(x: 100, y: 100))
            myBezier.addLineToPoint(CGPoint(x: 200, y: 100))
            myBezier.moveToPoint(CGPoint(x: 100, y: 200))
            myBezier.addLineToPoint(CGPoint(x: 200, y: 200))
            UIColor.orangeColor().setStroke()
            myBezier.stroke()
        }
    }
    

    一个圆

    我们可以通过下面的方法绘制一个圆弧:

    var bezier1 = UIBezierPath()
    bezier1.addArcWithCenter(CGPointMake(100, 300), radius: 50, startAngle: 0, endAngle: 1.0, clockwise: true)
    bezier1.stroke()
    

    其中,startAngle 是以 x 轴正方向为起点,clockwise 则是用来标记是否为顺时针方向。

    加个框

    stroke 是画线,fill 是填充。所以实心圆可以这么画:

    UIColor.redColor().setFill()
    UIColor.greenColor().setStroke()
    var bezier2 = UIBezierPath()
    bezier2.addArcWithCenter(CGPointMake(100, 300), radius: 50, startAngle: 0, endAngle: 20, clockwise: true)
    bezier2.lineWidth = 10
    bezier2.stroke()
    bezier2.fill()
    

    空心圆

    其实当初看到 UIBezierPath 是因为公司的项目里用这个实现了一个中间是透明正方形的黑色蒙版,用在了二维码扫描上。接下来就试着做一个黑色的蒙版,然后中间有一个透明的正方形。

    先来看看 mask 的用法:

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            var path = UIBezierPath()
            path.addArcWithCenter(view.center, radius: 100, startAngle: 0, endAngle: CGFloat(M_PI), clockwise: true)
            path.closePath()
            var mask = CAShapeLayer()
            mask.path = path.CGPath
            view.layer.mask = mask
        }
    }
    

    接下来我们可以简单的实现以下这个中空的效果:

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let imageView = UIImageView(image: UIImage(named: "avatar"))
            imageView.center = view.center
            view.addSubview(imageView)
    
            let maskLayer = CALayer()
            maskLayer.frame = view.frame
            maskLayer.backgroundColor = UIColor.blackColor().CGColor
            maskLayer.opacity = 0.6
            view.layer.addSublayer(maskLayer)
    
            let rectSize = CGFloat(100)
            let shapeLayer = CAShapeLayer()
            shapeLayer.frame = view.layer.frame
            var path = UIBezierPath(rect: CGRectMake((view.frame.width-rectSize)/2, (view.frame.height-rectSize)/2, rectSize, rectSize))
            path.appendPath(UIBezierPath(rect: view.layer.frame))
            shapeLayer.path = path.CGPath
            shapeLayer.fillRule = kCAFillRuleEvenOdd
    
            maskLayer.mask = shapeLayer
        }
    }
    

    简单记录一下 fillRule ,它有两种值:

    • kCAFillRuleNonZero,非零。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径 的交点情况。从0开始计数,路径从左向右穿过射线则计数加1,从右向左穿过射线则计数减1。得出计数结果后,如果结果是0,则认为点在图形外部,否则认为 在内部。

    • kCAFillRuleEvenOdd,奇偶。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部。


  • 相关阅读:
    LambdaExpressions(Lambda表达式)
    解密淘宝网的开源架构(转)
    使用Action、Func和Lambda表达式
    ASP.NET中进行消息处理(MSMQ) 二
    从内存变化看.NET代码执行机理(一)
    提高C#编程水平的50个要诀
    其他概念
    asp.net mvc相关开源项目
    为性能和可伸缩性做架构和设计上的Review
    你可能不知道的C#语言特性
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4946421.html
Copyright © 2020-2023  润新知