rendering
As the picture shows, there is a small arrow on the left side of the picture
The principle of
The principle is simple: take an image, MaskImgae, stretch it and then crop it to fit the outline
steps
Here pick the point to say, layout of what to do according to their own will. I fixed the display size of the image to 102 * 152
1. Stretch the MaskImgae
// Set the stretch range
let stretchInsets = UIEdgeInsetsMake(30.28.23.28)
// The image to be stretched
let stretchImage = UIImage(named: "SenderImageNodeMask")
// Stretch
let bubbleMaskImage = stretchImage.resizableImage(withCapInsets: stretchInsets, resizingMode: .stretch)
Copy the code
Stretching looks like this
2. Set clipping area for imageView
Here my imageView is called chatImgView. The stretched image above is temporarily assigned to chatImgView, just to show you the effect. Please remember to change it back if there is an assignment
All right, let’s crop it
// Create a new layer
let layer = CALayer(a)// Set the layer to display the stretched MaskImgae
layer.contents = bubbleMaskImage.cgImage
// Set the stretch range (note: here the CGRect of contentsCenter is proportional (not absolute))
layer.contentsCenter = self.CGRectCenterRectForResizableImage(bubbleMaskImage)
// Set the layer size to the same as chatImgView
layer.frame = CGRect(x: 0, y: 0, width: 102, height: 152)
// Set the scale
layer.contentsScale = UIScreen.main.scale
// Set the opacity
layer.opacity = 1
// Set the clipping range
self.chatImgView.layer.mask = layer
// Set clipping out the excess area
self.chatImgView.layer.masksToBounds = true
Copy the code
func CGRectCenterRectForResizableImage(_ image: UIImage) -> CGRect {
// LXFLog("\(image.capInsets)")
CapInsets UIEdgeInsetsMake(30, 28, 23, 28)
return CGRect(
x: image.capInsets.left / image.size.width,
y: image.capInsets.top / image.size.height,
width: (image.size.width - image.capInsets.right - image.capInsets.left) / image.size.width,
height: (image.size.height - image.capInsets.bottom - image.capInsets.top) / image.size.height
)
}
Copy the code
And you’re done
Explain a little bit
UIEdgeInsetsMake
MaskImgae is 56 by 50 in size
// UIEdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat)
UIEdgeInsetsMake(30.28.23.28)
Copy the code
The red range is the range to be stretched.
contentsCenter
This is a full stretch of an area, default if not set
CGRect(x: 0, y: 0, width: 1, height: 1)
Copy the code
I’m just going to scale it so let’s see what happens if I don’t set the contentsCenter value
var contentsCenter: CGRect { get set }
Description
The rectangle that defines how the layer contents are scaled
ifThe layer's contents are resized.Animatable.
Copy the code
If the contents of the layer are resized, then this rectangle is defined to tell the layer how the contents of the layer are resized
That’s clear. Our image is stretched and then drawn to the layer. In order to display our image correctly, we need to tell the layer how it was stretched. Yes, the scope specified by the code below
UIEdgeInsetsMake(30.28.23.28)
Copy the code
However, as mentioned above, the CGRect assigned by contentsCenter is proportional, not absolute, so now we have to get the proportional value through (30, 28, 23, 28). The conversion method is given above. Is CGRectCenterRectForResizableImage we to print the image. The capInsets content
LXFLog("\(image.capInsets)")
LXFLog("\(image.capInsets.top)")
LXFLog("\(image.capInsets.bottom)")
LXFLog("\(image.capInsets.left)")
LXFLog("\(image.capInsets.right)")
Copy the code
Print the result
UIEdgeInsets(Top: 30.0, left: 28.0, bottom: 23.0, Right: 28.0Copy the code
Good, now in combination with the code in the following figure and CGRectCenterRectForResizableImage proportion was very clear how to
Attached is related project: Swift 3.0 high imitation wechat