छाया प्रसार और धब्बा को कैसे नियंत्रित करें?


112

मैंने स्केच में यूआई तत्वों को डिज़ाइन किया है, और उनमें से एक में धब्बा 1 के साथ एक छाया है और फैली हुई है। मैंने देखा कि लेयर संपत्ति और लेयर के लिए doc में कुछ भी नहीं है जिसका नाम स्प्रेड या ब्लर, या समतुल्य कुछ भी है (केवल नियंत्रण था) केवल परछाई) कैसे धुंधला और फैलने जैसी चीजों को नियंत्रित कर सकता है?

संपादित करें:

यहाँ स्केच में मेरी सेटिंग्स हैं: और यहाँ मैं अपनी छाया जैसा दिखना चाहता हूँ:स्केच छाया सेटिंग्स


छाया चाहती थी




और यहां यह इस समय कैसा दिखता है: ध्यान दें, आपको छाया को देखने के लिए तस्वीर पर क्लिक करना होगा।

वर्तमान छाया

मेरा कोड इस प्रकार है:

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
}

Ios (प्लेटफ़ॉर्म), डिज़ाइन (सॉफ़्टवेयर स्केच का उपयोग) और कोर-ग्राफिक्स (यह छाया खींचने के लिए UIBezierPath का उपयोग करना संभव है, व्हिह प्रासंगिक हो सकता है) सभी प्रासंगिक हैं, मैं नहीं देखता कि उन्हें क्यों करना चाहिए हटाया जाना।
क्वांटालिनुसाइट

आप केवल उस सफेद दृश्य के लिए छाया चाहते हैं?
ओ-मकार

5
ऐसा लगता है कि स्केच और CoreAnimation फ्रेमवर्क में अलग-अलग मेट्रिक्स हैं, क्योंकि यह हमेशा iOS पर और स्केच में समान पैरामेट्स के साथ अलग दिखता है।
तैमूर बर्निकोविच

आह। डिजाइनरों के साथ काम करने की खुशियाँ जो ऐसे उपकरणों का उपयोग करती हैं जो आईओएस के काम करने के तरीके से बहुत कम या कोई समानता नहीं रखते हैं। यदि आप स्केच के बजाय पेंटकोड जैसी किसी चीज़ पर जाते हैं तो यह न केवल आईओएस काम करेगा बल्कि यह आपको वह कोड देगा जिसकी आपको आवश्यकता है। :-)
फोगमिस्टर

यदि आपने स्केच में त्रिज्या और धब्बा दोनों को सेट किया है तो क्या होगा?
व्लादिमीर

जवाबों:


257

यहाँ सही सटीकता के साथ UIView की परत में सभी 6 स्केच छाया गुण लगाने का तरीका बताया गया है:

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 स्क्रीनशॉट; सही: स्केच आयत।

ध्यान दें:

  • एक गैर-शून्य का उपयोग करते समय spread, यह कैलेयर के आधार पर एक पथ को हार्डकोड करता है bounds। यदि परत की सीमा कभी बदलती है, तो आप applySketchShadow()विधि को फिर से कॉल करना चाहेंगे ।

हम्म। स्केच में, यदि आप फैलाव लागू करते हैं, तो यह 'बाहर निकल जाता है', जहां छाया का धुंधला / ढाल शुरू होता है। जिसका अर्थ है - यह निरंतर छाया-रंग पर रहता है, जब तक धब्बा शुरू नहीं होता है। लेकिन अगर हम शैडोलेयर को चारों ओर घुमाते हैं, तो छाया केवल उस परत से शुरू होगी, है ना? (कहते हैं प्रसार 10 है, छाया केवल 10 के ऑफसेट के बाद शुरू होगी, जहां स्केच में, धुंधला / ढाल 10 के ऑफसेट के बाद शुरू होगी)। तो वे वास्तव में मेल नहीं खाते हैं, है ना?
Stephan

1
@ मैंने यह जानना चाहा है कि आपने यह फॉर्मूला कैसे हासिल किया ?!
हाशम अबोनजामी

2
आप सेट करना भूल गए maskToBounds = false
स्कॉट्टीब्लाड्स

1
जैसा कि ऊपर उल्लेख किया गया है स्कॉटीब्लाड्स, यह बिना काम नहीं करेगा maskToBounds = false। एक उदाहरण जहां यह विफल हो जाएगा इस छाया को लागू करते समय ए UIButton
जोस

5
क्या यह shadowRadius = blur / UIScreen.main.scaleहार्ड-कोडिंग के विपरीत होना चाहिए blur / 2.0? या, वहाँ 2 से विभाजित करने के लिए एक और कारण है? @matchifang क्या आपने इसका पता लगाया?
JWK

59

आप यह कोशिश कर सकते हैं .... आप मूल्यों के साथ खेल सकते हैं। 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

स्विफ्ट 2.0 में बेसिक शैडो का उदाहरण

आउटपुट


2
जानकारी गलत है, ऑफ़सेट प्रसार का नियंत्रण नहीं है, यह x और y का नियंत्रण है।
क्वांटालिनुसाइट ५०

@Quantaliinuxite मैंने गलती से उन टिप्पणियों को इंटरचेंज कर दिया है जिनके उत्तर मैंने अपडेट किए हैं
O-mkar

ठीक है, और अब मेरे प्रश्न का मूल आता है: मैं प्रसार को कैसे नियंत्रित करूं?
क्वांटालिनुसाइट 6

@Quantaliinuxite अपडेट किया गया कोड अब आप की जरूरत 2.1 को बदल दें
O-mkar

जवाब के लिए धन्यवाद। यहाँ मैं शैडो ओपेसिटी को समझ नहीं पा रहा हूँ (इसका उपयोग क्यों किया जाता है)।
सुनीता

11

स्केच 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
            }
        }
    }
}

आउटपुट

डेमो

इसे कैसे उपयोग करे

डेमो


क्या आपको layer.shadowRadius * 2छायाबेल गेट्टर के लिए नहीं लौटना चाहिए
बेर्कुको

7

इस कोड ने मेरे लिए बहुत अच्छा काम किया:

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

स्केच में धुंधला मूल्य कोर एनिमेशन के छाया त्रिज्या से मेल नहीं खाता है।
Cifilter

जो हमारे लिए पर्याप्त रूप से काम कर रहा था वह समाप्त हो गया था और स्केच में कोर एनिमेशन की छाया त्रिज्या के लिए कलंक मूल्य को कम कर रहा था।
1

2

उन लोगों के लिए जो एक पूर्वनिर्धारित पथ पर एक छाया लागू करने का प्रयास कर रहे हैं (उदाहरण के लिए एक परिपत्र दृश्य के लिए), यहां मैंने जो कुछ बताया है:

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

मैं कुछ उदाहरण बाद में पोस्ट करूंगा, लेकिन इसने मेरे लिए परिपत्र विचारों के लिए जगह पर काम किया है।


यह "लगभग" काम करता है लेकिन जब आप के 1साथ xऔर के प्रसार का उपयोग करते हैं तो प्रसार गलत होता है y 0 shapeLayer.applyShadow(color: .black, alpha: 1, x: 0, y: 0, blur: 0, spread: 1, path: path)। इस मामले में छाया में एक ऑफसेट है, जबकि यह नहीं होना चाहिए। यहां त्रिभुज की छाया सभी दिशाओं में 1px फैली होनी चाहिए ibb.co/YjwRb9B
Jan

1

इस पोस्ट के आधार पर मेरा समाधान उत्तर: (स्विफ्ट 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

0

मैं वास्तव में यहां पोस्ट किए गए उत्तर और टिप्पणियों में सुझाव पसंद करता हूं । इस तरह मैंने उस समाधान को संशोधित किया:

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)

-1

यह इतिहास में थोड़ा पच सकता है, लेकिन शायद कुछ एक ही मुद्दा था। मैंने स्वीकार किए गए उत्तर से कोड नमूने का उपयोग किया। हालांकि प्रभाव काफी भिन्न हैं: - स्केच में समान मूल्य की तुलना में y मान लगभग आधा होना चाहिए - मैंने नेविगेशन बार पर छाया लागू करने की कोशिश की और प्रभाव बहुत भिन्न है - स्केच के समान मूल्यों का उपयोग करते समय मुश्किल से दिखाई देता है।

तो ऐसा लगता है कि विधि पूरी तरह से स्केच मापदंडों को प्रतिबिंबित नहीं कर रही है। कोई संकेत?


यह कोई जवाब नहीं है - टिप्पणी टिप्पणियों में जाती हैं!
डेव वाई
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.