【问题标题】:Swift how to mask shape layer to blur layerSwift如何掩盖形状层以模糊层
【发布时间】:2021-10-15 10:43:55
【问题描述】:

我在做一个进度圈,我想让它的轨迹有模糊的效果,有什么办法可以做到吗?

原来的轨迹是这样的(轨迹路径是透明的,我希望它是模糊的)

这是我的尝试

let outPutViewFrame = CGRect(x: 0, y: 0, width: 500, height: 500)
let circleRadius: CGFloat = 60
let circleViewCenter = CGPoint(x: outPutViewFrame.width / 2 , y: outPutViewFrame.height / 2)
let circleView = UIView()
let progressWidth: CGFloat = 8

circleView.frame.size = CGSize(width: (circleRadius + progressWidth) * 2, height: (circleRadius + progressWidth) * 2)
circleView.center = circleViewCenter


let circleTrackPath = UIBezierPath(arcCenter: CGPoint(x: circleView.frame.width / 2, y: circleView.frame.height / 2), radius: circleRadius, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
let blur = UIBlurEffect(style: .light)
let blurEffect = UIVisualEffectView(effect: blur)
blurEffect.frame = circleView.bounds
blurEffect.mask(withPath: circleTrackPath, inverse: false)

extension UIView {

    func mask(withPath path: UIBezierPath, inverse: Bool = false) {
    
        let maskLayer = CAShapeLayer()

        if inverse {
            path.append(UIBezierPath(rect: self.bounds))
            maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
        }
        
        maskLayer.path = path.cgPath
        maskLayer.lineWidth = 5
        maskLayer.lineCap = CAShapeLayerLineCap.round
       

        self.layer.mask = maskLayer
    }
}

【问题讨论】:

  • 你的意思是你想让你的轨迹路径有模糊效果?我在您的示例图像中看不到任何模糊。圆圈似乎在源图像上方以部分透明的蓝色绘制。

标签: swift calayer mask cashapelayer


【解决方案1】:
  • maskLayer.fillRule 设置为evenOdd,即使不是inversed

      if inverse {
          path.append(UIBezierPath(rect: self.bounds))
      }
      maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
    
  • 使用大圆圈和小圆圈创建circleTrackPath

      let circleCenter = CGPoint(x: circleView.frame.width / 2, y: circleView.frame.height / 2)
      let circleTrackPath = UIBezierPath(ovalIn: 
          CGRect(origin: circleCenter, size: .zero)
              .insetBy(dx: circleRadius, dy: circleRadius))
      // smaller circle
      circleTrackPath.append(CGRect(origin: circleCenter, size: .zero)
              .insetBy(dx: circleRadius * 0.8, dy: circleRadius * 0.8))
    
  • circleTrackPath.usesEvenOddFillRule 设置为真:

      circleTrackPath.usesEvenOddFillRule = true
    

现在你有一个模糊的完整圆圈。未模糊的圆弧部分可以作为另一个子层实现。

这是一个可以粘贴到 Playground 的 MCVE:

let container = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))

// change this to a view of your choice
let image = UIImageView(image: UIImage(named: "my_image"))
let blur = UIVisualEffectView(effect: UIBlurEffect(style: .light))
container.addSubview(image)
blur.frame = image.frame
container.addSubview(blur)
let outer = image.bounds.insetBy(dx: 30, dy: 30)
let path = UIBezierPath(ovalIn: outer)
path.usesEvenOddFillRule = true
path.append(UIBezierPath(ovalIn: outer.insetBy(dx: 10, dy: 10)))

let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
maskLayer.fillRule = .evenOdd
blur.layer.mask = maskLayer
container // <--- playground quick look this

使用我的个人资料图片作为背景,这会产生:

【讨论】:

    猜你喜欢
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 2017-12-24
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    相关资源
    最近更新 更多