You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现非矩形圆角效果?iOS图层遮罩问题求助

实现非矩形圆角遮罩效果的解决方案

问题描述

我想要实现非矩形圆角效果,最初尝试创建4个图层绘制路径制作圆角,但线条不够流畅所以放弃。之后用遮罩实现,实际效果和预期不符,附上我的代码,请问怎么实现预期的遮罩效果?

func makeGuideline() {
        let roundedRectangleLayer = CAShapeLayer()
        let roundedRectangleWidth = frame.width * 0.6
        let roundedRectangleHeight = frame.height * 0.4
        let path = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: (frame.width / 2 - roundedRectangleWidth / 2), y: (frame.height / 2 - roundedRectangleHeight / 2)), size: CGSize(width: roundedRectangleWidth, height: roundedRectangleHeight)), cornerRadius: 10)
        
        roundedRectangleLayer.path = path.cgPath
        roundedRectangleLayer.fillColor = .none
        roundedRectangleLayer.strokeColor = UIColor.red.cgColor
        roundedRectangleLayer.lineWidth = 1
        
        let maskLayer = CAShapeLayer()
        let maskPath = UIBezierPath()
        let maskWidth = roundedRectangleWidth * 0.2
        let maskHeight = roundedRectangleHeight * 0.3
        
        maskPath.move(to: CGPoint(x: frame.width / 2 - maskWidth / 2, y: frame.height / 2 - roundedRectangleHeight / 2))
        maskPath.addLine(to: CGPoint(x: frame.width / 2 - maskWidth / 2 + maskWidth, y: frame.height / 2 - roundedRectangleHeight / 2))
        
        maskLayer.fillColor = .none
        maskLayer.path = maskPath.cgPath
        maskLayer.strokeColor = UIColor.blue.cgColor
        maskLayer.lineWidth = 1
        maskLayer.fillRule = .evenOdd
        
        roundedRectangleLayer.mask = maskLayer

        layer.addSublayer(roundedRectangleLayer)
 }

问题分析

你的遮罩路径仅绘制了一条直线,且遮罩层未设置填充内容。CAShapeLayer作为遮罩时,只有填充区域会显示原图层内容,线条部分无法生效。结合预期效果(顶部中间带缺口的圆角矩形),直接绘制包含缺口的完整路径比使用遮罩更简单流畅。

正确实现方案

通过单一路径结合evenOdd填充规则,直接绘制带缺口的圆角矩形,代码如下:

func makeGuideline() {
    let targetLayer = CAShapeLayer()
    let rectWidth = frame.width * 0.6
    let rectHeight = frame.height * 0.4
    let rectOrigin = CGPoint(x: (frame.width - rectWidth)/2, y: (frame.height - rectHeight)/2)
    let baseRect = CGRect(origin: rectOrigin, size: CGSize(width: rectWidth, height: rectHeight))
    let cornerRadius: CGFloat = 10
    
    // 创建基础圆角矩形路径
    let path = UIBezierPath(roundedRect: baseRect, cornerRadius: cornerRadius)
    
    // 添加顶部中间的缺口路径(可根据需求调整缺口尺寸和位置)
    let gapWidth = rectWidth * 0.2
    let gapHeight = rectHeight * 0.3
    let gapRect = CGRect(
        x: rectOrigin.x + (rectWidth - gapWidth)/2,
        y: rectOrigin.y - gapHeight/2,
        width: gapWidth,
        height: gapHeight
    )
    path.append(UIBezierPath(rect: gapRect))
    
    // 设置填充规则为evenOdd,实现缺口镂空效果
    targetLayer.path = path.cgPath
    targetLayer.fillColor = UIColor.clear.cgColor
    targetLayer.strokeColor = UIColor.red.cgColor
    targetLayer.lineWidth = 1
    targetLayer.fillRule = .evenOdd
    
    layer.addSublayer(targetLayer)
}

关键说明

  • 单图层绘制完整路径,避免多图层拼接导致的线条不流畅问题
  • evenOdd填充规则会让路径重叠区域镂空,刚好实现缺口效果
  • 若需要其他位置的缺口,只需调整gapRect的坐标和尺寸即可

内容的提问来源于stack exchange,提问作者msgu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:42:42