[ios] 그림자 확산 및 흐림을 제어하는 ​​방법은 무엇입니까?

저는 스케치에서 UI 요소를 디자인했으며 그중 하나에는 블러 1과 스프레드 0이있는 그림자가 있습니다. 뷰 레이어 속성에 대한 문서를 살펴 보았고 레이어에 스프레드 또는 블러라는 이름의 어떤 것도 포함되지 않았습니다 (유일한 컨트롤은 단순히 shadowOpacity) 흐림 및 확산과 같은 것을 어떻게 제어 할 수 있습니까?

편집하다:

Sketch의 내 설정은 다음과 같습니다.

그리고 여기에 내 그림자를 원하는 모양이 있습니다.스케치 그림자 설정

그림자 구함

그리고 지금의 모습입니다. 참고, 실제로 그림자를 보려면 사진을 클릭해야합니다.

현재 그림자

내 코드는 다음과 같습니다.

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
}



답변

거의 완벽한 정확도로 6 개의 Sketch 그림자 속성을 UIView의 레이어에 모두 적용하는 방법은 다음과 같습니다.

extension CALayer {
  func applySketchShadow(
    color: UIColor = .black,
    alpha: Float = 0.5,
    x: CGFloat = 0,
    y: CGFloat = 2,
    blur: CGFloat = 4,
    spread: CGFloat = 0)
  {
    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)

예:

여기에 이미지 설명 입력

왼쪽 : iPhone 8 UIView 스크린 샷; 오른쪽 : 스케치 직사각형.

노트 :

  • 0이 아닌을 사용 하면 CALayer를 spread기반으로 경로를 하드 코딩합니다 bounds. 레이어의 경계가 변경되면 applySketchShadow()메서드를 다시 호출해야 합니다.

답변

당신은 이것을 시도 할 수 있습니다 …. 당신은 가치를 가지고 놀 수 있습니다. shadowRadius지시 흐림의 양. shadowOffset그림자가가는 곳을 나타냅니다.

스위프트 2.0

let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height

demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4)  //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds =  false
demoView.layer.shadowPath = shadowPath.CGPath

스위프트 3.0

let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height

demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.black.cgColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4)  //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds =  false
demoView.layer.shadowPath = shadowPath.cgPath

스프레드가있는 예

스프레드가있는 예

기본 그림자를 만들려면

    demoView.layer.cornerRadius = 2
    demoView.layer.shadowColor = UIColor.blackColor().CGColor
    demoView.layer.shadowOffset = CGSizeMake(0.5, 4.0); //Here your control your spread
    demoView.layer.shadowOpacity = 0.5
    demoView.layer.shadowRadius = 5.0 //Here your control your blur

Swift 2.0의 기본 그림자 예제

산출


답변

Swift 4에서 IBDesignable 및 IBInspectable을 사용한 스케치 섀도우

나란히 스케치 및 XCODE

그림자 예

암호

@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
            }
        }
    }
}

산출

데모 출력

사용 방법

데모


답변

이 코드는 저에게 매우 잘 작동했습니다.

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


답변

미리 정의 된 경로에 그림자를 적용하려는 사람들을 위해 (예 : 원형보기와 같이) 다음과 같은 결과를 얻었습니다.

extension CALayer {
    func applyShadow(color: UIColor = .black,
                     alpha: Float = 0.5,
                     x: CGFloat = 0,
                     y: CGFloat = 2,
                     blur: CGFloat = 4,
                     spread: CGFloat = 0,
                     path: UIBezierPath? = nil) {
        shadowColor = color.cgColor
        shadowOpacity = alpha
        shadowRadius = blur / 2
        if let path = path {
            if spread == 0 {
                shadowOffset = CGSize(width: x, height: y)
            } else {
                let scaleX = (path.bounds.width + (spread * 2)) / path.bounds.width
                let scaleY = (path.bounds.height + (spread * 2)) / path.bounds.height

                path.apply(CGAffineTransform(translationX: x + -spread, y: y + -spread).scaledBy(x: scaleX, y: scaleY))
                shadowPath = path.cgPath
            }
        } else {
            shadowOffset = CGSize(width: x, height: y)
            if spread == 0 {
                shadowPath = nil
            } else {
                let dx = -spread
                let rect = bounds.insetBy(dx: dx, dy: dx)
                shadowPath = UIBezierPath(rect: rect).cgPath
            }
        }
        shouldRasterize = true
        rasterizationScale = UIScreen.main.scale
    }
}

나중에 몇 가지 예제를 게시 할 것이지만 이것은 저에게 원형 뷰에 대해 제대로 작동했습니다.


답변

이 게시물을 기반으로 한 내 솔루션은 다음과 같이 답합니다. (Swift 3)

let shadowPath = UIBezierPath(rect: CGRect(x: -1,
                                           y: -2,
                                           width: target.frame.width + 2,
                                           height: target.frame.height + 2))

target.layer.shadowColor = UIColor(hexString: shadowColor).cgColor
target.layer.shadowOffset = CGSize(width: CGFloat(shadowOffsetX), height: CGFloat(shadowOffsetY))
target.layer.masksToBounds = false
target.layer.shadowOpacity = Float(shadowOpacity)
target.layer.shadowPath = shadowPath.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)