在箭头形状的面具周围画一个边框

时间:2022-05-15 23:21:37

In my app I need a contour of an arrow that will get filled with color as user progresses through some activity. To create an arrow shape in my view I've subclassed UIView for use in Interface Builder:

在我的应用中,我需要一个箭头的轮廓,当用户通过一些活动时,它会被填充上颜色。为了在我的视图中创建一个箭头形状,我对UIView进行了子类化,以便在接口构建器中使用:

@IBDesignable
class MaskedView: UIView {

    var maskImageView = UIImageView()

    @IBInspectable var maskImage: UIImage? {
        didSet {
            maskImageView.image = maskImage
            maskImageView.contentMode = .scaleAspectFit
            maskImageView.frame = bounds
            mask = maskImageView
        }
    }

}

Then in IB I select an arrow image, which creates the needed shape:

然后在IB中选择一个箭头图像,创建所需的形状:

在箭头形状的面具周围画一个边框

在箭头形状的面具周围画一个边框

Here the view has gray background for demonstration purposes. Actually I need it to be white with arrow appearing as a black contour:

这里的视图有灰色背景以供演示。实际上我需要它是白色的,箭头是黑色的轮廓:

在箭头形状的面具周围画一个边框

So basically I need a border around my arrow mask. What is the best way to achieve this result?

基本上,我需要在箭头蒙版周围加上边框。达到这个结果的最佳方式是什么?

1 个解决方案

#1


1  

yourView should be in clearColor. Adjust CGPoint as per ur need with the help of extension.

你的视图应该是清晰的颜色。根据需要在扩展的帮助下调整CGPoint。

let arrow = UIBezierPath.arrow(from: CGPoint(x: 50, y: 100), to: CGPoint(x: 200, y: 50),
                                       tailWidth: 10, headWidth: 25, headLength: 40)
let caLay = CAShapeLayer()
caLay.path = arrow.cgPath
yourView.layer.mask = caLay

let borderLayer = CAShapeLayer()
borderLayer.path = arrow.cgPath // Reuse the Bezier path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.green.cgColor
borderLayer.lineWidth = 5
borderLayer.frame = greenview.bounds
yourView.layer.addSublayer(borderLayer)



extension UIBezierPath {

    class func arrow(from start: CGPoint, to end: CGPoint, tailWidth: CGFloat, headWidth: CGFloat, headLength: CGFloat) -> Self {
        let length = hypot(end.x - start.x, end.y - start.y)
        let tailLength = length - headLength

        func p(_ x: CGFloat, _ y: CGFloat) -> CGPoint { return CGPoint(x: x, y: y) }
        var points: [CGPoint] = [
            p(0, tailWidth / 2),
            p(tailLength, tailWidth / 2),
            p(tailLength, headWidth / 2),
            p(length, 0),
            p(tailLength, -headWidth / 2),
            p(tailLength, -tailWidth / 2),
            p(0, -tailWidth / 2)
        ]

        let cosine = (end.x - start.x) / length
        let sine = (end.y - start.y) / length
        var transform = CGAffineTransform(a: cosine, b: sine, c: -sine, d: cosine, tx: start.x, ty: start.y)
        let path = CGMutablePath()
        path.addLines(between: points, transform: transform)
        path.closeSubpath()
        return self.init(cgPath: path)
    }

}

#1


1  

yourView should be in clearColor. Adjust CGPoint as per ur need with the help of extension.

你的视图应该是清晰的颜色。根据需要在扩展的帮助下调整CGPoint。

let arrow = UIBezierPath.arrow(from: CGPoint(x: 50, y: 100), to: CGPoint(x: 200, y: 50),
                                       tailWidth: 10, headWidth: 25, headLength: 40)
let caLay = CAShapeLayer()
caLay.path = arrow.cgPath
yourView.layer.mask = caLay

let borderLayer = CAShapeLayer()
borderLayer.path = arrow.cgPath // Reuse the Bezier path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.green.cgColor
borderLayer.lineWidth = 5
borderLayer.frame = greenview.bounds
yourView.layer.addSublayer(borderLayer)



extension UIBezierPath {

    class func arrow(from start: CGPoint, to end: CGPoint, tailWidth: CGFloat, headWidth: CGFloat, headLength: CGFloat) -> Self {
        let length = hypot(end.x - start.x, end.y - start.y)
        let tailLength = length - headLength

        func p(_ x: CGFloat, _ y: CGFloat) -> CGPoint { return CGPoint(x: x, y: y) }
        var points: [CGPoint] = [
            p(0, tailWidth / 2),
            p(tailLength, tailWidth / 2),
            p(tailLength, headWidth / 2),
            p(length, 0),
            p(tailLength, -headWidth / 2),
            p(tailLength, -tailWidth / 2),
            p(0, -tailWidth / 2)
        ]

        let cosine = (end.x - start.x) / length
        let sine = (end.y - start.y) / length
        var transform = CGAffineTransform(a: cosine, b: sine, c: -sine, d: cosine, tx: start.x, ty: start.y)
        let path = CGMutablePath()
        path.addLines(between: points, transform: transform)
        path.closeSubpath()
        return self.init(cgPath: path)
    }

}