【问题标题】:Swift - Cut hole in shadow layerSwift - 在阴影层切洞
【发布时间】:2017-08-31 03:12:13
【问题描述】:

我想在 Swift3、iOS 的 UIView 的阴影层中“切一个洞”

我有一个容器 (UIView),它有 2 个孩子:

  • 一个 UIImageView
  • 该图像顶部的一个 UIView(“叠加层”)

我想给叠加层一个阴影并切出该阴影的内部矩形,以在 ImageView 的边缘创建类似发光的效果
由于图像占用了屏幕宽度,因此嵌入辉光至关重要
到目前为止我的代码:

let glowView = UIView(frame: CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight))
glowView.layer.shadowPath = UIBezierPath(roundedRect: container.bounds, cornerRadius: 4.0).cgPath
glowView.layer.shouldRasterize = true
glowView.layer.rasterizationScale = UIScreen.main.scale
glowView.layer.shadowOffset = CGSize(width: 1.0, height: 1.0)
glowView.layer.shadowOpacity = 0.4

container.addSubview(imageView)
container.addSubview(glowView)

现在的结果如下所示:

现在我想剪掉较暗的内部部分,以便只保留边缘的阴影
知道如何实现这一目标吗?

【问题讨论】:

  • 在图像视图之前添加发光视图。这应该工作
  • 对不起,没提,但我不能这样做,因为图像占用了所有宽度,并且需要插入发光
  • @skaldesh ,如果你还在看,有一个更简单的方法来做到这一点!我回答了,干杯

标签: ios swift swift3 calayer shadow


【解决方案1】:

幸运的是,今天(2020 年)现在很容易

现在很容易做到这一点:

这就是全部

import UIKit
class GlowBox: UIView {
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        backgroundColor = .clear
        layer.shadowOpacity = 1
        layer.shadowColor = UIColor.red.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.shadowRadius = 3
        
        let p = UIBezierPath(
             roundedRect: bounds.insetBy(dx: 0, dy: 0),
             cornerRadius: 4)
        let hole = UIBezierPath(
             roundedRect: bounds.insetBy(dx: 2, dy: 2),
             cornerRadius: 3)
             .reversing()
        p.append(hole)
        layer.shadowPath = p.cgPath
    }
}

一个非常方便的提示:

当您添加(即 .append )两条这样的贝塞尔路径时...

第二个必须是“正常”或“反转”。

注意接近末尾的代码行:

             .reversing()

像大多数程序员一样,我永远记不得在不同情况下应该是“正常”还是“逆向”!!

简单的解决方案...

很简单,两个都试试!

无论是否使用.reversing(),都可以尝试一下

它会以一种或另一种方式工作! :)

【讨论】:

  • 很酷的解决方案:)
  • 感谢@skaldesh - 你摇滚。是的,这是其中一件幸运的是,这些天它变得非常容易!欢呼
【解决方案2】:

感谢Mihai Fratu's answer 我能够创建一个完全满足我需求的 UIBezierPath
我在这里发布我的代码,以防以后有人遇到同样的问题

let innerRadius: CGFloat = 32.0 * UIScreen.main.scale
let shadowPath: UIBezierPath = UIBezierPath(roundedRect: self.view.bounds, cornerRadius: self.cornerRadius)
//shadowPath.append(UIBezierPath(roundedRect: self.view.bounds.insetBy(dx: 8, dy: 8), cornerRadius: self.cornerRadius))
let shadowWidth: CGFloat = 8.0 // Do this as wide as you want
var outterPath = UIBezierPath()
// Start at the top left corner with an x offset of the cornerRadius
outterPath.move(to: CGPoint(x: self.cornerRadius, y: 0))

// Draw a line to the top right corner
outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width - self.cornerRadius, y: 0))
//Draw the round top right corner
outterPath.addArc(withCenter: CGPoint(x: glowView.bounds.size.width - self.cornerRadius, y: self.cornerRadius), radius: self.cornerRadius, startAngle: (3 * CGFloat.pi) / 2, endAngle: 0, clockwise: true)

// Draw a line to the bottom right corner
outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width, y: glowView.bounds.size.height - self.cornerRadius))
// Draw the round bottom right corner
outterPath.addArc(withCenter: CGPoint(x: glowView.bounds.size.width - self.cornerRadius, y: glowView.bounds.size.height -  self.cornerRadius), radius: self.cornerRadius, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: true)

// Draw a line to the bottom left corner
outterPath.addLine(to: CGPoint(x: self.cornerRadius, y: glowView.bounds.size.height))
// Draw the round bottom left corner
outterPath.addArc(withCenter: CGPoint(x: self.cornerRadius, y: glowView.bounds.size.height -  self.cornerRadius), radius: self.cornerRadius, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: true)

// Draw a line to the top left corner
outterPath.addLine(to: CGPoint(x: 0.0, y: self.cornerRadius))
// Draw the round top left corner
outterPath.addArc(withCenter: CGPoint(x: self.cornerRadius, y: self.cornerRadius), radius: self.cornerRadius, startAngle: CGFloat.pi, endAngle: (3 * CGFloat.pi) / 2, clockwise: true)

// Move to the inner start point and add the paths counterclockwise to prevent the filling of the inner area
outterPath.move(to: CGPoint(x: shadowWidth + innerRadius, y: shadowWidth))
// Draw the inner top left corner
outterPath.addArc(withCenter: CGPoint(x: shadowWidth + innerRadius, y: shadowWidth + innerRadius), radius: innerRadius, startAngle: (3 * CGFloat.pi) / 2, endAngle: CGFloat.pi, clockwise: false)

// Draw a line to the inner bottom left corner
outterPath.addLine(to: CGPoint(x: shadowWidth, y: glowView.bounds.size.height - innerRadius - shadowWidth))
// Draw the inner bottom left corner
outterPath.addArc(withCenter: CGPoint(x: shadowWidth + innerRadius, y: glowView.bounds.size.height - innerRadius - shadowWidth), radius: innerRadius, startAngle: CGFloat.pi, endAngle: CGFloat.pi / 2, clockwise: false)

// Draw a line to the inner bottom right corner
outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width - innerRadius - shadowWidth, y: glowView.bounds.size.height - shadowWidth))
// Draw the inner bottom right corner
outterPath.addArc(withCenter: CGPoint(x: glowView.bounds.size.width - innerRadius - shadowWidth, y: glowView.bounds.size.height - innerRadius - shadowWidth), radius: innerRadius, startAngle: CGFloat.pi / 2, endAngle: 0, clockwise: false)

// Draw a line to the inner top right corner
outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width - shadowWidth, y: shadowWidth + innerRadius))
// Draw the inner top right corner
outterPath.addArc(withCenter: CGPoint(x: glowView.bounds.size.width - innerRadius - shadowWidth, y: shadowWidth + innerRadius), radius: innerRadius, startAngle: 0, endAngle: (3 * CGFloat.pi) / 2, clockwise: false)

// Draw a line to the inner top left corner
outterPath.addLine(to: CGPoint(x: shadowWidth + innerRadius, y: shadowWidth))
outterPath.close()

【讨论】:

    【解决方案3】:

    尝试使用它作为你的阴影路径:

    let shadowWidth = 2.0 // Do this as wide as you want
    var outterPath = UIBezierPath()
    outterPath.move(to: CGPoint(x: shadowWidth, y: 0))
    outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width, y: 0))
    outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width, y: glowView.bounds.size.height))
    outterPath.addLine(to: CGPoint(x: 0.0, y: glowView.bounds.size.height))
    outterPath.addLine(to: CGPoint(x: 0.0, y: 0.0))
    outterPath.addLine(to: CGPoint(x: shadowWidth, y: 0.0))
    outterPath.addLine(to: CGPoint(x: shadowWidth, y: glowView.bounds.size.height - shadowWidth))
    outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width - shadowWidth, y: glowView.bounds.size.height - shadowWidth))
    outterPath.addLine(to: CGPoint(x: glowView.bounds.size.width - shadowWidth, y: shadowWidth))
    outterPath.addLine(to: CGPoint(x: shadowWidth, y: shadowWidth))
    outterPath.close()
    

    这不会创建圆角矩形,但对上面的代码进行一些更改,您应该也可以添加它们。

    【讨论】:

    • 谢谢,这为我的方法打下了很好的基础!我会做一个答案并在那里参考你的答案!
    • 任何人在这里谷歌搜索,有一种非常简单的方法可以做到这一点(也有正确的角落等),我输入了一个答案
    猜你喜欢
    • 1970-01-01
    • 2017-07-31
    • 2011-04-02
    • 2016-06-14
    • 2013-07-26
    • 2017-08-03
    • 1970-01-01
    • 2013-09-03
    相关资源
    最近更新 更多