Swift - Border Inside Masked Image

2019-08-13 15:43发布

问题:

I have a masked image that's utilized by a UIBezierPath() and I'd like to have a border around the masked portion rather than the original image. I've come this close in my (countless number) attempt through trial and error and, tirelessly, given up. Any easier way to do this?

This is how far I've come to my goal:

I'd love to have the border go inward! :-(

Swift 2 Code:

let picture = UIImageView(image: UIImage(named: "myPicture.png"))
picture.layer.contentMode = .ScaleAspectFit
picture.layer.clipsToBounds = true

let maskLayer = CAShapeLayer()
picture.layer.mask = maskLayer

maskLayer.frame = CGRect(origin: CGPointZero, size: picture.image.size)
let radius = picture.size.width/2
let center = CGPoint(x: picture.size.width/2, y: picture.size.height/2)

let path = UIBezierPath()
            path.moveToPoint(center)
            path.addArcWithCenter(center, radius: radius, startAngle: 0, endAngle: CGFloat(M_PI*2.0*0.2), clockwise: true)

maskLayer.path = path.CGPath

picture.layer.mask = maskLayer

picture.layer.borderWidth = 3
picture.layer.borderColor = UIColor.purpleColor().CGColor
picture.layer.cornerRadius = picture.layer.bounds.width/2

回答1:

Assuming I understand what you mean by "I'd love to have the border go inward" - I would recommend using another CAShapeLayer to display your border as a stroked path, and adding it as a sublayer to your image view's layer.

You just have to set your pass in the path you defined for your mask, set your strokeColor and lineWidth, and set fillColor to clearColor.

Something like this should do the trick:

// insert your image here
guard let img = UIImage(named: "4.png") else {
    return
}

// frame of your image view
let frame = CGRectInset(view.bounds, 10, 10)

// your picture view
let pictureView = UIImageView(image: img)
pictureView.frame = frame
pictureView.contentMode = .ScaleAspectFit
pictureView.clipsToBounds = true

// the radius and center of your path
let radius = pictureView.frame.size.width*0.5
let center = CGPoint(x: pictureView.frame.size.width*0.5, y: pictureView.frame.size.height*0.5)

// your masking & stroking path
let path = UIBezierPath()
path.moveToPoint(center)
path.addArcWithCenter(center, radius: radius, startAngle: 0, endAngle: CGFloat(M_PI*2.0*0.8), clockwise: true)
path.closePath()

// the layer used to mask the image view
let maskLayer = CAShapeLayer()
maskLayer.frame = pictureView.bounds
maskLayer.path = path.CGPath
pictureView.layer.mask = maskLayer

// the layer used to draw the border
let strokeLayer = CAShapeLayer()
strokeLayer.frame = pictureView.bounds
strokeLayer.fillColor = UIColor.clearColor().CGColor
strokeLayer.path = path.CGPath
strokeLayer.strokeColor = UIColor.purpleColor().CGColor
strokeLayer.lineWidth = 10
pictureView.layer.addSublayer(strokeLayer)

view.addSubview(pictureView)

Gives the following output:

Also, I would note that the code you provided in the OP didn't even compile - please always copy and paste in your code from the IDE instead of trying to type it out yourself!