Search code examples
cocoacalayernsview

Using custom shadow path on NSView


Unfortunately it seems that setting the shadow attributes on the layer directly doesn't work:

let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
shadowView.wantsLayer = true
shadowView.layer!.backgroundColor = .white
shadowView.layer!.shadowRadius = 50
shadowView.layer!.shadowColor = .black
shadowView.layer!.shadowOffset = CGSize(width: 0, height: -30)
shadowView.layer!.shadowPath = CGPath(roundedRect: shadowView.bounds, cornerWidth: 25, cornerHeight: 25, transform: nil)

Setting the NSView.shadow property instead works:

let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))let shadow = NSShadow()
shadow.shadowBlurRadius = 50
shadow.shadowColor = .black
shadow.shadowOffset = CGSize(width: 0, height: -30)
shadowView.shadow = shadow
shadowView.wantsLayer = true
shadowView.layer!.backgroundColor = .white

But NSShadow doesn't support a custom path. What's the easiest way to set a shadow with a custom path?


Solution

  • Edited Answer - after comments...

    The reason your shadow code didn't seem to work was because you were missing two property settings:

    // need these two properties set
    shadowView.layer!.masksToBounds = false
    shadowView.layer!.shadowOpacity = 1.0
    

    Quick example (I moved the shadowView origin to 100,100 so we can see the full shadow):

    class ViewController: NSViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let shadowView = NSView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
            view.addSubview(shadowView)
            
            shadowView.wantsLayer = true
            
            shadowView.layer!.backgroundColor = .white
            shadowView.layer!.shadowRadius = 50
            shadowView.layer!.shadowColor = .black
            shadowView.layer!.shadowOffset = CGSize(width: 0, height: -30)
            shadowView.layer!.shadowPath = CGPath(roundedRect: shadowView.bounds, cornerWidth: 25, cornerHeight: 25, transform: nil)
            
            // need these two properties set
            shadowView.layer!.masksToBounds = false
            shadowView.layer!.shadowOpacity = 1.0  // set as desired
            
        }
        
    }
    

    Result:

    enter image description here