2016-02-15 59 views
6
  • 的Xcode 7.2
  • 斯威夫特2

我試圖合成圖像,什麼我打電話了 「BlurFilterMask」。這是一個CALayer的,我動態與斯威夫特的代碼添加,這裏是BlurFilterMask:添加CALayer的子層集中在UIImageView的

class BlurFilterMask : CALayer { 

    private let GRADIENT_WIDTH : CGFloat = 50.0 

    var origin : CGPoint = CGPointZero { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 

    var diameter : CGFloat = 50.0 { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 

    override init() { 
     super.init() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    override func drawInContext(ctx: CGContext) { 
     CGContextSaveGState(ctx) 

     let clearRegionRadius : CGFloat = self.diameter * 0.5 
     let blurRegionRadius : CGFloat = clearRegionRadius + GRADIENT_WIDTH 

     let baseColorSpace = CGColorSpaceCreateDeviceRGB(); 
     let colours : [CGFloat] = [0.0, 0.0, 0.0, 0.0,  // Clear region 
     0.0, 0.0, 0.0, 0.6] // blur region color 
     let colourLocations : [CGFloat] = [0.0, 0.0] 
     let gradient = CGGradientCreateWithColorComponents (baseColorSpace, colours, colourLocations, 2) 


     CGContextDrawRadialGradient(ctx, gradient, self.origin, clearRegionRadius, self.origin, blurRegionRadius, .DrawsAfterEndLocation); 

    } 

} 

在我UIViewController.viewDidLoad()我打電話addMaskOverlay(),這裏是實現:

func addMaskOverlay(){ 
     let blurFilterMask = BlurFilterMask() 

     blurFilterMask.diameter = 80 
     blurFilterMask.frame = heroImageView.bounds 
     blurFilterMask.origin = heroImageView.center 
     blurFilterMask.shouldRasterize = true 

     heroImageView.layer.addSublayer(blurFilterMask) 

     blurFilterMask.setNeedsDisplay() 
    } 

不管模擬器我運行,無論是iPhone 5或iPhone 6或ipad 2,用於實施例中,我總是得到相同的中心,寬度和高度:

  • 打印(heroImageView.center)=(300.0,67.5)
  • 打印(CGRectGetWidth(heroImageView.bounds))= 600.0
  • 打印(CGRectGetHeight(heroImageView.bounds))//135.0

但我的BlurFilterMask的中心總是不同的地方,這取決於設備模擬器和它永遠不會發生在的UIImageView的中心,例如在iPhone 5:

enter image description here

這裏是iPhone 6:

enter image description here

我想也許我需要垂直居中和水平在我的CALayer BlurFilterMask中心的約束,所以我嘗試添加約束:

heroImageView.layer.addSublayer(blurFilterMask) 

let xConstraint = NSLayoutConstraint(item: blurFilterMask, attribute: .CenterX, relatedBy: .Equal, toItem: heroImageView, attribute: .CenterX, multiplier: 1, constant: 0) 

let yConstraint = NSLayoutConstraint(item: blurFilterMask, attribute: .CenterY, relatedBy: .Equal, toItem: heroImageView, attribute: .CenterY, multiplier: 1, constant: 0) 

heroImageView.addConstraint(xConstraint) 
heroImageView.addConstraint(yConstraint) 

但我不能約束添加到CALayer的,我不認爲,我得到一個當我嘗試錯誤:

終止應用程序由於未捕獲的異常 'NSInvalidArgumentException',原因:「* + [NSLayoutConstraint constraintWithItem:屬性:relatedBy:toItem:屬性:乘數:常數:]:約束物品必須各自是實例的UIView,或NSLayoutGuide的。「**

好像這個問題可能是制約因素,但是如果我不能約束添加到CALayer的...

該代碼沒有幫助...

不知道從哪裏去,任何建議將不勝感激。

+0

你嘗試基於設備'UIScreen.mainScreen做你的測量()。bounds'? –

+0

你是說從UIScreen.mainScreen.bounds和我的UIImageView.bounds使用減法來找到UIImageView的中心? –

+0

因爲如果你說只使用UIScreen.mainScreen.bounds,它會將我的BlurFilterMask置於顯示的整個View的中心,而這不是我想要完成的。 –

回答

3

問題是,當調用viewDidLoad時,佈局尚未完成,因此您的測量值將從視圖控制器的初始狀態中獲取,最有可能來自故事板大小,如果這就是您正在使用的。

一旦佈局完成並且最終尺寸爲heroImageView已知,您需要致電blurFilterMask

你可以通過覆蓋viewDidLayoutSubviews來做到這一點,這是...

調用以通知視圖控制器其視圖剛剛佈置了它的子視圖。

the docs因爲有一些條件,但在你的情況下,這樣做的工作讓你有這個..

class ViewController: UIViewController { 

    @IBOutlet var heroImageView: UIImageView! 

    var blurFilterMask:BlurFilterMask! = nil 

    func resetMaskOverlay(){ 

     if blurFilterMask == nil { 

      blurFilterMask = BlurFilterMask() 

      blurFilterMask.diameter = 120 

      heroImageView.layer.addSublayer(blurFilterMask) 

     } 

     blurFilterMask.frame = heroImageView.bounds 
     blurFilterMask.origin = heroImageView.center 

    } 


    override func viewDidLayoutSubviews() { 
     resetMaskOverlay() 
    } 

} 

我以爲這行BlurFilterMask

CGContextTranslateCTM(ctx, 0.0, yDiff)*/ 

的意思是什麼註釋掉,因爲它沒有太大的意義離開...

class BlurFilterMask : CALayer { 

    let GRADIENT_WIDTH : CGFloat = 50.0 

    var origin : CGPoint = CGPointZero { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 
    var diameter : CGFloat = 50.0 { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 

    override func drawInContext(ctx: CGContext) { 
     CGContextSaveGState(ctx) 

     let clearRegionRadius : CGFloat = self.diameter * 0.5 
     let blurRegionRadius : CGFloat = clearRegionRadius + GRADIENT_WIDTH 

     let baseColorSpace = CGColorSpaceCreateDeviceRGB(); 
     let colours : [CGFloat] = [0.0, 0.0, 0.0, 0.0,  // Clear region 
      0.0, 0.0, 0.0, 0.6] // blur region color 
     let colourLocations : [CGFloat] = [0.0, 0.0] 
     let gradient = CGGradientCreateWithColorComponents (baseColorSpace, colours, colourLocations, 2) 


     CGContextDrawRadialGradient(ctx, gradient, self.origin, clearRegionRadius, self.origin, blurRegionRadius, .DrawsAfterEndLocation); 

    } 

} 

test1-5stest1-6s+

+0

我有一種感覺,你是正確的,但我將無法檢查,直到明天晚些時候,儘快更新,謝謝 –

+0

糟糕是,我平常的錯誤。你需要一次只有一次的機會來阻止這種事情發生。請參閱編輯 - 我已將該圖層添加爲伊娃來跟蹤它。 –

+0

奇怪。確切的代碼在我的模擬器上運行,它有點閃爍,但沒有什麼不能用一些alpha解決。或者離開圖層並重置其原點。 –

相關問題