2015-12-30 2 views
0

Мне нужно нарисовать анимированный линейный градиент, который обновляется на каждом кадре, используя CADisplayLink. Прямо в полноэкранном контексте с CoreGraphics медленнее, я получаю около 40 кадров в секунду при полной загрузке процессора на iPad Air.Самый быстрый способ рисовать линейный градиент в полноэкранном режиме в iOS

Какой самый быстрый способ сделать это?

+1

Почему бы не использовать ['CAGradientLayer'] (https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CAGradientLayer_class/index.html)? Рисование с помощью CA почти наверняка будет намного быстрее (и использовать гораздо меньше CPU), чем CG. –

+0

Спасибо, Курт, я обновил ответ. – carton

ответ

1

Update

Как @Kurt Revis отметил в комментарии по этому вопросу, собственно - и самый быстрый - способ сделать это состоит в использовании CAGradientLayer. Добавить CAGradientLayer на ваш взгляд, что наполняет его пределы, то:

func updateGradient() { 
    // Sample random gradient 
    let gradientLocs:[CGFloat] = [0.0, 0.5, 1.0] 
    let gradientColors:[CGColorRef] = [ 
     UIColor.whiteColor().CGColor, 
     UIColor.init(colorLiteralRed: 0.0, green: 0.0, blue: 0.25*Float(arc4random())/Float(UINT32_MAX), alpha: 1.0).CGColor, 
     UIColor.blackColor().CGColor 
    ] 

    // Disable implicit animations if this is called via CADisplayLink 
    CATransaction.begin() 
    CATransaction.setDisableActions(true) 

    // Draw to existing CAGradientLayer 
    gradientBackgroundLayer.colors = gradientColors 
    gradientBackgroundLayer.locations = gradientLocs 

    CATransaction.commit() 
} 

Старый ответ

После нескольких экспериментов, я закончил с использованием CoreGraphics сделать градиент в 1px широкий CGImage и затем положите на UIImageView, чтобы сделать масштабирование. Я получаю твердые 60fps при температуре около 7-11% загрузки процессора, в зависимости от того, сколько цветов градиента содержит:

Подкласса UIImageView с contentMode установлен в ScaleToFill, а затем вызвать следующий через CADisplayLink для непрерывной анимации.

func updateGradient() { 
    // Sample random gradient 
    let gradientLocs:[CGFloat] = [0.0, 0.5, 1.0] 
    let gradientColors:[CGColorRef] = [ 
     UIColor.whiteColor().CGColor, 
     UIColor.init(colorLiteralRed: 0.0, green: 0.0, blue: 0.25*Float(arc4random())/Float(UINT32_MAX), alpha: 1.0).CGColor, 
     UIColor.blackColor().CGColor 
    ] 

    // Create context at 1px width and display height 
    let gradientWidth:Double = 1 
    let gradientHeight:Double = Double(UIScreen.mainScreen().bounds.height) 
    UIGraphicsBeginImageContext(CGSize(width: gradientWidth, height: gradientHeight)) 
    let buffer:CGContextRef = UIGraphicsGetCurrentContext()! 

    // Draw gradient into buffer 
    let colorspace = CGColorSpaceCreateDeviceRGB() 
    let gradient = CGGradientCreateWithColors(colorspace, gradientColors, gradientLocs) 
    CGContextDrawLinearGradient(
     buffer, 
     gradient, 
     CGPoint(x: 0.0, y: 0.0), 
     CGPoint(x: 0.0, y: gradientHeight), 
     CGGradientDrawingOptions.DrawsAfterEndLocation 
    ) 

    // Let UIImageView superclass handle scaling 
    image = UIImage.init(CGImage: CGBitmapContextCreateImage(buffer)!) 

    // Avoid memory leaks... 
    UIGraphicsEndImageContext() 
} 

Предостережение: этот подход будет работать только для горизонтальных или вертикальных линейных градиентов.

Есть ли лучшие способы сделать это?

 Смежные вопросы

  • Нет связанных вопросов^_^