iOS开发:UIImageView底部绘制UIBezierPath曲线位置异常问题
Got it, let's work through why your ellipse is landing in the middle of imgCamera instead of sticking to the bottom. The issue boils down to two key things: your bezier path is probably centered by default, and the way you're setting up the layer mask in draw(_:) isn't optimized for positioning. Here's how to fix it step by step:
1. Rewrite the Bezier Path to Anchor to the Bottom
First, we need to make sure your pathCurvedForView method generates an ellipse that sits at the bottom of the view. Replace your existing implementation with this one, which calculates the ellipse's position explicitly:
func pathCurvedForView(givenView: UIView) -> UIBezierPath { // Adjust these values to tweak the ellipse's size let ellipseWidthRatio: CGFloat = 0.8 // 80% of the view's width let ellipseHeightRatio: CGFloat = 0.25 // 25% of the view's height let ellipseWidth = givenView.bounds.width * ellipseWidthRatio let ellipseHeight = givenView.bounds.height * ellipseHeightRatio // Calculate origin to center horizontally and lock to the bottom let originX = (givenView.bounds.width - ellipseWidth) / 2 let originY = givenView.bounds.height - ellipseHeight let ellipseRect = CGRect(x: originX, y: originY, width: ellipseWidth, height: ellipseHeight) return UIBezierPath(ovalIn: ellipseRect) }
2. Fix the Layer Mask Setup (Avoid draw(_:))
Using draw(_:) to set up layer masks isn't the best practice—it's designed for Core Graphics immediate drawing, not layer management. Instead, use layoutSubviews (which triggers when the view's size changes) to set up your mask reliably:
override func layoutSubviews() { super.layoutSubviews() applyBottomEllipseMask() } private func applyBottomEllipseMask() { let shapeLayer = CAShapeLayer() shapeLayer.path = pathCurvedForView(givenView: imgCamera).cgPath shapeLayer.frame = imgCamera.bounds // This will make imgCamera only show the bottom ellipse area imgCamera.layer.mask = shapeLayer }
Wait—Did You Want to Draw an Ellipse On Top of the View?
If you're not trying to mask the view (i.e., you just want an ellipse shape displayed at the bottom of imgCamera), skip the mask and add the shape layer as a sublayer instead:
private func addBottomEllipseShape() { let shapeLayer = CAShapeLayer() shapeLayer.path = pathCurvedForView(givenView: imgCamera).cgPath shapeLayer.frame = imgCamera.bounds // Customize the appearance as needed shapeLayer.fillColor = UIColor.systemBlue.cgColor shapeLayer.strokeColor = UIColor.black.cgColor shapeLayer.lineWidth = 2.0 imgCamera.layer.addSublayer(shapeLayer) }
Call this method in viewDidLoad or layoutSubviews to render the ellipse.
Why Your Original Code Didn't Work
- Your original
pathCurvedForViewlikely generated a centered ellipse instead of anchoring to the bottom. - Initializing
CAShapeLayerwithCAShapeLayer(layer: imgCamera.layer)is unnecessary—this constructor is for copying layer properties, not creating a new shape layer. - Using
draw(_:)for layer mask setup can lead to unexpected behavior, as it's triggered every time the view needs to redraw (not just when layout changes).
内容的提问来源于stack exchange,提问作者Chirag Shah

