Ios 如何控制阴影扩散和模糊?

Ios 如何控制阴影扩散和模糊?,ios,swift,uiview,core-graphics,Ios,Swift,Uiview,Core Graphics,我在sketch中设计了UI元素,其中一个元素的阴影为模糊1,扩散为0。我查看了views图层属性的文档,该图层没有任何命名为spread或blur的内容,也没有任何等效内容(唯一的控件只是shadowOpacity)。如何控制模糊和扩散 以下是我在草图中的设置: 我希望我的影子是这样的: 以下是目前的情况: 注意,你必须点击图片才能真正看到阴影 我的代码如下: func setupLayer(){ view.layer.cornerRadius = 2 view.laye

我在sketch中设计了UI元素,其中一个元素的阴影为模糊1,扩散为0。我查看了views图层属性的文档,该图层没有任何命名为spread或blur的内容,也没有任何等效内容(唯一的控件只是shadowOpacity)。如何控制模糊和扩散

以下是我在草图中的设置:

我希望我的影子是这样的:

以下是目前的情况:

注意,你必须点击图片才能真正看到阴影

我的代码如下:

func setupLayer(){
    view.layer.cornerRadius = 2
    view.layer.shadowColor = Colors.Shadow.CGColor
    view.layer.shadowOffset = CGSize(width: 0, height: 1)
    view.layer.shadowOpacity = 0.9
    view.layer.shadowRadius = 5
}

你可以试试这个。。。。你可以利用这些价值观。
阴影半径
指示模糊量<代码>阴影偏移量指示阴影的位置

Swift 2.0

Swift 3.0

传播的例子

创建基本阴影的步骤

Swift 2.0中的基本阴影示例


此代码对我来说非常有效:

yourView.layer.shadowOpacity = 0.2 // opacity, 20%
yourView.layer.shadowColor = UIColor.black.cgColor
yourView.layer.shadowRadius = 2 // HALF of blur
yourView.layer.shadowOffset = CGSize(width: 0, height: 2) // Spread x, y
yourView.layer.masksToBounds = false

我基于此帖子的解决方案回复:(Swift 3)


以下是如何以近乎完美的精度将所有6个草图阴影特性应用于UIView的图层:

extension CALayer {
  func applySketchShadow(
    color: UIColor = .black,
    alpha: Float = 0.5,
    x: CGFloat = 0,
    y: CGFloat = 2,
    blur: CGFloat = 4,
    spread: CGFloat = 0)
  {
    masksToBounds = false
    shadowColor = color.cgColor
    shadowOpacity = alpha
    shadowOffset = CGSize(width: x, height: y)
    shadowRadius = blur / 2.0
    if spread == 0 {
      shadowPath = nil
    } else {
      let dx = -spread
      let rect = bounds.insetBy(dx: dx, dy: dx)
      shadowPath = UIBezierPath(rect: rect).cgPath
    }
  }
}
假设我们要代表以下内容:

您可以通过以下方式轻松做到这一点:

myView.layer.applySketchShadow(
  color: .black, 
  alpha: 0.5, 
  x: 0, 
  y: 0, 
  blur: 4, 
  spread: 0)
或者更简洁地说:

myView.layer.applySketchShadow(y: 0)
例如:

左:iPhone8UIView屏幕截图;右:绘制矩形

注:

  • 当使用非零的
    排列
    时,它会根据CALayer的
    边界
    对路径进行硬编码。如果层的边界发生变化,则需要再次调用
    applySketchShadow()
    方法

在Swift 4中使用IBDesignable和IBInspectable绘制阴影

并排绘制和XCODE

代码

输出

如何使用它


对于那些试图将阴影应用于预定义路径(例如圆形视图)的人,我的结论如下:

extensioncalayer{
func applyShadow(颜色:UIColor=.black,
alpha:Float=0.5,
x:CGFloat=0,
y:CGFloat=2,
模糊:CGFloat=4,
价差:CGFloat=0,
路径:UIBezierPath?=nil){
shadowColor=color.cgColor
阴影不透明度=α
阴影半径=模糊/2
如果let path=path{
如果排列==0{
阴影偏移=CGSize(宽度:x,高度:y)
}否则{
设scaleX=(path.bounds.width+(spread*2))/path.bounds.width
设scaleY=(path.bounds.height+(spread*2))/path.bounds.height
apply(CGAffineTransform(translationX:x+-spread,y:y+-spread).scaledBy(x:scaleX,y:scaleY))
阴影路径=path.cgPath
}
}否则{
阴影偏移=CGSize(宽度:x,高度:y)
如果排列==0{
阴影路径=零
}否则{
设dx=-扩散
设rect=bounds.insetBy(dx:dx,dy:dx)
shadowPath=UIBezierPath(rect:rect).cgPath
}
}
shouldRasterize=true
光栅化比例=UIScreen.main.scale
}
}

稍后我将发布一些示例,但这对我来说对循环视图非常有效。

这可能是历史上的一个小问题,但可能有些有相同的问题。我使用了来自已接受答案的代码示例。然而,效果却大不相同: -y值必须是草图中相同值的一半左右 -我试着在导航栏上应用阴影,效果非常不同——使用和草图相同的值时几乎看不见

因此,该方法似乎完全没有反映草图参数。 有什么提示吗?

我真的很喜欢评论中的提示和建议。我就是这样修改该解决方案的:

extension UIView {
  func applyShadow(color: UIColor, alpha: Float, x: CGFloat, y: CGFloat, blur: CGFloat, spread: CGFloat) {
    layer.masksToBounds = false
    layer.shadowColor = color.cgColor
    layer.shadowOpacity = alpha
    layer.shadowOffset = CGSize(width: x, height: y)
    layer.shadowRadius = blur / UIScreen.main.scale
    if spread == 0 {
      layer.shadowPath = nil
    } else {
      let dx = -spread
      let rect = bounds.insetBy(dx: dx, dy: dx)
      layer.shadowPath = UIBezierPath(rect: rect).cgPath
    }
  }
}
用法:

myButton.applyShadow(color: .black, alpha: 0.2, x: 0, y: 1, blur: 2, spread: 0)

标记ios(平台)、设计(软件草图的使用)和核心图形(可以使用UIBezierPath绘制阴影,这可能是相关的)都是相关的,我不明白为什么要删除它们。你只想将阴影用于白色视图吗?看起来草图和核心动画框架有不同的度量,因为它在iOS上和草图上总是看起来不一样,参数都是一样的。与使用与iOS工作方式几乎没有相似或根本没有相似之处的工具的设计师合作的乐趣。如果您使用像PaintCode而不是Sketch这样的工具,它不仅可以像iOS一样工作,还可以为您提供所需的代码。:-)如果您在草图中同时设置了半径和模糊度,该怎么办?信息是错误的,偏移量不是对扩散的控制,而是对x和y的控制。@quantalinuxite我无意中交换了注释我更新了答案右侧,现在是我问题的核心:我如何控制差价?@Quantaliinuxite更新代码现在将2.1更改为您需要的差价金额谢谢您的回答。在这里,我无法理解阴影不透明度(为什么要使用它)。草图中的模糊值与核心动画的阴影半径不匹配。最终对我们来说效果足够好的是将核心动画阴影半径的草图中的模糊值减半。扩散和偏移是不同的参数。别把人搞糊涂了!嗯。在草图中,如果应用“扩散”,它会“向外移动”,阴影的模糊/渐变从这里开始。这意味着-它保持不变的阴影颜色,直到模糊开始。但是如果我们移动阴影层,阴影将只从该层开始,对吗?(假设“扩散”为10,阴影将仅在偏移10后开始,而在草图中,模糊/渐变将在偏移10后开始)。所以他们真的不匹配,对吗?@senseve我很想知道你是怎么得到这个公式的?!您忘记设置
maskToBounds=false
。正如ScottyBl前面提到的那样
myView.layer.applySketchShadow(
  color: .black, 
  alpha: 0.5, 
  x: 0, 
  y: 0, 
  blur: 4, 
  spread: 0)
myView.layer.applySketchShadow(y: 0)
@IBDesignable class ShadowView: UIView {

    @IBInspectable var shadowColor: UIColor? {
        get {
            if let color = layer.shadowColor {
                return UIColor(cgColor: color)
            }
            return nil
        }
        set {
            if let color = newValue {
                layer.shadowColor = color.cgColor
            } else {
                layer.shadowColor = nil
            }
        }
    }

    @IBInspectable var shadowOpacity: Float {
        get {
            return layer.shadowOpacity
        }
        set {
            layer.shadowOpacity = newValue
        }
    }

    @IBInspectable var shadowOffset: CGPoint {
        get {
            return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
        }
        set {
            layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
        }

     }

    @IBInspectable var shadowBlur: CGFloat {
        get {
            return layer.shadowRadius
        }
        set {
            layer.shadowRadius = newValue / 2.0
        }
    }

    @IBInspectable var shadowSpread: CGFloat = 0 {
        didSet {
            if shadowSpread == 0 {
                layer.shadowPath = nil
            } else {
                let dx = -shadowSpread
                let rect = bounds.insetBy(dx: dx, dy: dx)
                layer.shadowPath = UIBezierPath(rect: rect).cgPath
            }
        }
    }
}
extension UIView {
  func applyShadow(color: UIColor, alpha: Float, x: CGFloat, y: CGFloat, blur: CGFloat, spread: CGFloat) {
    layer.masksToBounds = false
    layer.shadowColor = color.cgColor
    layer.shadowOpacity = alpha
    layer.shadowOffset = CGSize(width: x, height: y)
    layer.shadowRadius = blur / UIScreen.main.scale
    if spread == 0 {
      layer.shadowPath = nil
    } else {
      let dx = -spread
      let rect = bounds.insetBy(dx: dx, dy: dx)
      layer.shadowPath = UIBezierPath(rect: rect).cgPath
    }
  }
}
myButton.applyShadow(color: .black, alpha: 0.2, x: 0, y: 1, blur: 2, spread: 0)