向掩模图层添加边框

时间:2017-12-24 10:45:51

标签: ios swift calayer cashapelayer

我尝试使用遮罩层制作自定义形状UIButton并且我成功了

extension UIButton { 

  func mask(withImage image : UIImage , frame : CGRect ){

        let maskingLayer = CAShapeLayer()
        maskingLayer.frame = frame
        maskingLayer.contents = image.cgImage
        self.layer.mask = maskingLayer
    }
}

但我想在遮罩层添加一个边框(笔触)来表示已选择此按钮。

我尝试在遮罩层添加子图层

button.mask?.layer.borderColor = UIColor.black.cgColor
button.mask?.layer.borderWidth = 4

但由于按钮形状仍为矩形,因此无法正常工作。

我知道我可以使用CGMutablePath来定义形状

func mask(withPath path: CGMutablePath , frame : CGRect , color : UIColor) {

    let mask = CAShapeLayer()
    mask.frame = frame
    mask.path = path
    self.layer.mask = mask

    let shape = CAShapeLayer()
    shape.frame = self.bounds
    shape.path = path
    shape.lineWidth = 3.0
    shape.strokeColor = UIColor.black.cgColor
    shape.fillColor = color.cgColor

    self.layer.insertSublayer(shape, at: 0)
   //  self.layer.sublayers![0].masksToBounds = true
}

但是使用路径绘制这样复杂的形状是极其困难的

enter image description here

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

我能够使用PocketSVG

从图像(.svg)获取CGPath

但我面临另一个问题,即路径的比例等于原始的SVG,所以我设法缩放路径以适应框架,这里是完整的代码: -

extension UIView {
    func mask(withSvgName ImageName : String , frame : CGRect , color : UIColor){

            let svgutils = SvgUtils()
            let paths = svgutils.getLayerFromSVG(withImageName: ImageName)
            let mask = CAShapeLayer()
            mask.frame = frame
            let newPath = svgutils.resizepath(Fitin: frame, path: paths[0].cgPath)
            mask.path = newPath
            self.layer.mask = mask

            let shape = CAShapeLayer()
            shape.frame = self.bounds
            shape.path = newPath
            shape.lineWidth = 2.0
            shape.strokeColor = UIColor.black.cgColor
            shape.fillColor = color.cgColor
            self.layer.insertSublayer(shape, at: 0)

        }
}

和实用程序类

import Foundation
import PocketSVG

class SvgUtils{


    func getLayerFromSVG(withImageName ImageName : String ) -> [SVGBezierPath]{

        let url = Bundle.main.url(forResource: ImageName, withExtension: "svg")!

        var paths = [SVGBezierPath]()

        for path in SVGBezierPath.pathsFromSVG(at: url) {

            paths.append(path)
        }

        return paths
    }

    func resizepath(Fitin frame : CGRect , path : CGPath) -> CGPath{


        let boundingBox = path.boundingBox
        let boundingBoxAspectRatio = boundingBox.width / boundingBox.height
        let viewAspectRatio = frame.width  / frame.height
        var scaleFactor : CGFloat = 1.0
        if (boundingBoxAspectRatio > viewAspectRatio) {
            // Width is limiting factor

            scaleFactor = frame.width / boundingBox.width
        } else {
            // Height is limiting factor
            scaleFactor = frame.height / boundingBox.height
        }


        var scaleTransform = CGAffineTransform.identity
        scaleTransform = scaleTransform.scaledBy(x: scaleFactor, y: scaleFactor)
        scaleTransform.translatedBy(x: -boundingBox.minX, y: -boundingBox.minY)

        let scaledSize = boundingBox.size.applying(CGAffineTransform (scaleX: scaleFactor, y: scaleFactor))
       let centerOffset = CGSize(width: (frame.width - scaledSize.width ) / scaleFactor * 2.0, height: (frame.height - scaledSize.height) /  scaleFactor * 2.0 )
        scaleTransform = scaleTransform.translatedBy(x: centerOffset.width, y: centerOffset.height)
        //CGPathCreateCopyByTransformingPath(path, &scaleTransform)
        let  scaledPath = path.copy(using: &scaleTransform)


        return scaledPath!
    }

}

只需像这样使用它

button.mask(withSvgName: "your_svg_fileName", frame: button.bounds, color: UIColor.green)