try! swift - advanced graphics with core animation

57
Advanced Graphics with Core Animation ティムオリバー

Upload: tim-oliver

Post on 21-Jan-2018

1.533 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: try! Swift - Advanced Graphics with Core Animation

Advanced Graphics with Core Animation

ティム•オリバー

Page 2: try! Swift - Advanced Graphics with Core Animation

• Core Animationのアニメーションの実装方法

• Core Animationを少し紹介する

• CALayer のスブクラスの利用方法

Overview

Page 3: try! Swift - Advanced Graphics with Core Animation

@TimOliverAU

• 2015年3月Realmに入った

•オーストラリアのパースの出身

• iOS開発をやってるのは約6年間

•カラオケが大好き!

Page 4: try! Swift - Advanced Graphics with Core Animation
Page 5: try! Swift - Advanced Graphics with Core Animation

My Relation with Japan

•帰国してから日本語の勉強を始めた

• 1996年に千葉県の小学校入学

• 2007年、新潟県のスキー場でワーホリ

• 2013年、pixivでiOS開発

Page 6: try! Swift - Advanced Graphics with Core Animation
Page 7: try! Swift - Advanced Graphics with Core Animation

iComics

•とんでもない画像データ

• DRMフリー•コミック•リーダー

• Core Animationを結構利用している

• (おまけに、Realmも! ^_^)

Page 8: try! Swift - Advanced Graphics with Core Animation

What’s Core Animation?

Page 9: try! Swift - Advanced Graphics with Core Animation

© Apple Inc.

• UIKitから下のレベル

What’s Core Animation?

•オペレーションをGPUに

転送させている

• UIViewと深くつながって

• iOSのグラフィクもアニメーションも管理する

Page 10: try! Swift - Advanced Graphics with Core Animation

•レイヤ•オブジェクトの階層

•ビットマップのようなコンテンツがセットできる

•このようにゲームの開発と同じのようになる!

Page 11: try! Swift - Advanced Graphics with Core Animation

Why is it good to know?

• iOSのグラフィックス•システムをもっと理解でき

る• 60FPSをもっと簡単に目指す事ができる!

• UIViewのAPIより、もっときれい、もっと複

雑なアニーションが可能性になる

•というわけで、アプリが他にも目立つ!

Page 12: try! Swift - Advanced Graphics with Core Animation

What about Core Graphics?

Page 13: try! Swift - Advanced Graphics with Core Animation

override func drawRect(_ rect: CGRect) {

//// General Declarations

let context = UIGraphicsGetCurrentContext()

//// Color Declarations

let fillColor = UIColor(red: 0.808, green: 0.000, blue: 0.000, alpha: 1.000)

//// Oval Drawing

let ovalPath = UIBezierPath(ovalInRect: CGRectMake(9, 8, 494, 494))

fillColor.setFill()

ovalPath.fill()

//// Bezier Drawing

let bezierPath = UIBezierPath()

bezierPath.moveToPoint(CGPointMake(334.34, 360.7))

bezierPath.addCurveToPoint(CGPointMake(196.21, 362.32), controlPoint1: CGPointMake(297.59, 381.88), controlPoint2: CGPointMake(247.05, 384.06))

bezierPath.addCurveToPoint(CGPointMake(99, 279.29), controlPoint1: CGPointMake(155.05, 344.84), controlPoint2: CGPointMake(120.9, 314.25))

bezierPath.addCurveToPoint(CGPointMake(134.91, 301.14), controlPoint1: CGPointMake(109.51, 288.03), controlPoint2: CGPointMake(121.77, 295.02))

bezierPath.addCurveToPoint(CGPointMake(276.84, 301.2), controlPoint1: CGPointMake(187.41, 325.7), controlPoint2: CGPointMake(239.9, 324.01))

bezierPath.addCurveToPoint(CGPointMake(276.79, 301.14), controlPoint1: CGPointMake(276.82, 301.18), controlPoint2: CGPointMake(276.8, 301.16))

bezierPath.addCurveToPoint(CGPointMake(146.29, 165.67), controlPoint1: CGPointMake(224.24, 260.93), controlPoint2: CGPointMake(179.57, 208.49))

bezierPath.addCurveToPoint(CGPointMake(128.78, 142.08), controlPoint1: CGPointMake(139.29, 158.68), controlPoint2: CGPointMake(134.03, 149.94))

bezierPath.addCurveToPoint(CGPointMake(255.76, 238.22), controlPoint1: CGPointMake(169.06, 178.78), controlPoint2: CGPointMake(233, 225.1))

bezierPath.addCurveToPoint(CGPointMake(166.43, 126.34), controlPoint1: CGPointMake(207.6, 187.52), controlPoint2: CGPointMake(164.68, 124.6))

bezierPath.addCurveToPoint(CGPointMake(313.57, 246.95), controlPoint1: CGPointMake(242.63, 203.25), controlPoint2: CGPointMake(313.57, 246.95))

bezierPath.addCurveToPoint(CGPointMake(319.19, 250.36), controlPoint1: CGPointMake(315.92, 248.27), controlPoint2: CGPointMake(317.73, 249.37))

bezierPath.addCurveToPoint(CGPointMake(323.2, 238.22), controlPoint1: CGPointMake(320.72, 246.46), controlPoint2: CGPointMake(322.07, 242.41))

bezierPath.addCurveToPoint(CGPointMake(290.8, 101), controlPoint1: CGPointMake(335.47, 193.64), controlPoint2: CGPointMake(321.46, 142.95))

bezierPath.addCurveToPoint(CGPointMake(386.26, 291.53), controlPoint1: CGPointMake(361.74, 143.82), controlPoint2: CGPointMake(403.78, 224.23))

bezierPath.addCurveToPoint(CGPointMake(384.77, 296.89), controlPoint1: CGPointMake(385.8, 293.34), controlPoint2: CGPointMake(385.3, 295.13))

bezierPath.addCurveToPoint(CGPointMake(385.38, 297.65), controlPoint1: CGPointMake(384.97, 297.14), controlPoint2: CGPointMake(385.18, 297.39))

bezierPath.addCurveToPoint(CGPointMake(406.4, 378.93), controlPoint1: CGPointMake(420.41, 341.35), controlPoint2: CGPointMake(410.78, 387.67))

bezierPath.addCurveToPoint(CGPointMake(334.34, 360.7), controlPoint1: CGPointMake(387.4, 341.82), controlPoint2: CGPointMake(352.22, 353.17))

bezierPath.closePath()

bezierPath.miterLimit = 4;

UIColor.whiteColor().setFill()

bezierPath.fill()

//// Text Drawing

let textRect = CGRectMake(35, 144, 50, 140)

let textTextContent = NSString(string: "{")

let textStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle

textStyle.alignment = .Left

let textFontAttributes = [NSFontAttributeName: UIFont.systemFontOfSize(107), NSForegroundColorAttributeName: UIColor.whiteColor(), NSParagraphStyleAttributeName: textStyle]

let textTextHeight: CGFloat = textTextContent.boundingRectWithSize(CGSizeMake(textRect.width, CGFloat.infinity), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: textFontAttributes, context: nil).size.height

CGContextSaveGState(context)

CGContextClipToRect(context, textRect);

textTextContent.drawInRect(CGRectMake(textRect.minX, textRect.minY + (textRect.height - textTextHeight) / 2, textRect.width, textTextHeight), withAttributes: textFontAttributes)

CGContextRestoreGState(context)

//// Text 2 Drawing

let text2Rect = CGRectMake(440, 143, 50, 140)

let text2TextContent = NSString(string: "}")

let text2Style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle

text2Style.alignment = .Left

let text2FontAttributes = [NSFontAttributeName: UIFont.systemFontOfSize(107), NSForegroundColorAttributeName: UIColor.whiteColor(), NSParagraphStyleAttributeName: text2Style]

let text2TextHeight: CGFloat = text2TextContent.boundingRectWithSize(CGSizeMake(text2Rect.width, CGFloat.infinity), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: text2FontAttributes, context: nil).size.height

CGContextSaveGState(context)

CGContextClipToRect(context, text2Rect);

text2TextContent.drawInRect(CGRectMake(text2Rect.minX, text2Rect.minY + (text2Rect.height - text2TextHeight) / 2, text2Rect.width, text2TextHeight), withAttributes: text2FontAttributes)

CGContextRestoreGState(context)

}

Page 14: try! Swift - Advanced Graphics with Core Animation

•完全にCPUで実行

•Core Animationと合わせ

たらかなりにいい!

•前の世代のデバイスで非

常に遅い可能性

•画像作成するAPI

Core Graphics

Page 15: try! Swift - Advanced Graphics with Core Animation

PaintCode on the Mac App

Store

Page 16: try! Swift - Advanced Graphics with Core Animation

So. Core Animation?

import QuartzCore

let newLayer = CALayer()

newLayer.frame = CGRectMake(0, 0, 100, 100)

newLayer.backgroundColor = UIColor.redColor().CGColor

•レイヤ•オブジェクトの階層で実装

•基本的なクラスは CALayer

Page 17: try! Swift - Advanced Graphics with Core Animation

So. Core Animation?

import QuartzCore

let newLayer = CALayer()

newLayer.frame = CGRectMake(0, 0, 100, 100)

newLayer.backgroundColor = UIColor.redColor().CGColor

newLayer.cornerRadius = 10

•レイヤ•オブジェクトの階層で実装

•基本的なクラスは CALayer

Page 18: try! Swift - Advanced Graphics with Core Animation

CALayer

Where is it in UIKit?

UIViewUIView

Page 19: try! Swift - Advanced Graphics with Core Animation

CALayer

Where is it in UIKit?

public class UIView {

public var layer: CALayer { get }

}

UIView

Page 20: try! Swift - Advanced Graphics with Core Animation

Deeply integrated with UIView

public class UIView {

public var frame: CGRect {

get {

return self.layer.frame

}

set {

self.layer.frame = newValue

}

}

}

let newLayer = CALayer()

view.layer.addSublayer(newLayer)

• CALayerプロパティーがUIViewで示されてる

• ‘frame’ は CALayerの‘position’ と‘bounds’ プロパティーで計っている.

Page 21: try! Swift - Advanced Graphics with Core Animation

Why is it not a superclass?

• UIViewのlayerのクラスが変わる事もある。

•普通のサブクラスの実装で不可能

public class MyGradientClass : UIView {

override class func layerClass() -> AnyClass {

return CAGradientLayer.self

}

}

Page 22: try! Swift - Advanced Graphics with Core Animation

Mapping contents to CALayer

let trySwiftLogo = self.trySwiftLogo() as UIImage

let trySwiftLayer = CALayer()

trySwiftLayer.contents = trySwiftLogo.CGImage

(アニメーションも可!)

Page 23: try! Swift - Advanced Graphics with Core Animation

Managing the scale of CALayer contentstrySwiftLayer.contentsGravity

kCAGravityResize

kCAGravityResizeAspectFill

kCAGravityResizeAspect

kCAGravityCenter

Page 24: try! Swift - Advanced Graphics with Core Animation

Tweetbot

Page 25: try! Swift - Advanced Graphics with Core Animation

UIImage

UIImageVie

w

CALayer

kCAGravityLeft

CALayer

kCAGravityRight

Page 26: try! Swift - Advanced Graphics with Core Animation

Bitmap sampling in CALayer

trySwiftLayer.minificationFilter trySwiftLayer.magnificationFilter

kCAFilterTrilinearBest Quality

(Slowest)

kCAFilterLinear

Default

kCAFilterNearest

Lowest Quality (Fast)

Page 27: try! Swift - Advanced Graphics with Core Animation

Bitmap sampling in CALayer

Page 28: try! Swift - Advanced Graphics with Core Animation

Masking CALayer Objects

let myLayer = CALayer()

myLayer.contents = self.makeRedCircleImage().CGImage

let myMask = CALayer()

myMask.contents = self.makeMaskImage().CGImage

myLayer.mask = myMask

+ =

myLayer myMask

Page 29: try! Swift - Advanced Graphics with Core Animation

Device Layer

Pages Layer

Arrow Layer

Mask Layer

Page 30: try! Swift - Advanced Graphics with Core Animation

Adding Shadows to CALayer

let myLayer = view.layer

myLayer.shadowColor = UIColor.blackColor().CGColor

myLayer.shadowOpacity = 0.75

myLayer.shadowOffset = CGSizeMake(5, 10)

myLayer.shadowRadius = 10

// IMPORTANT FOR PERFORMANCE

let myShadowPath = UIBezierPath(roundedRect:

view.bounds, cornerRadius: 10)

myLayer.shadowPath = myShadowPath.CGPath

Page 31: try! Swift - Advanced Graphics with Core Animation

Transforming a CALayer

let myLayer = CALayer()

myLayer.contents = self.makeTrySwiftLogoImage().CGImage

var transform = CATransform3DIdentity

transform.m34 = 1.0 / -500

transform = CATransform3DRotate(transform, 45.0f * M_PI / 180.0, 0, 1, 0)

myLayer.transform = transform

Page 32: try! Swift - Advanced Graphics with Core Animation
Page 33: try! Swift - Advanced Graphics with Core Animation

Flipboard

Page 34: try! Swift - Advanced Graphics with Core Animation

Blend Modes with CALayer

let myBlendLayer = CALayer()

myBlendLayer.setValue(false, forKey: “allowsGroupBlending”) // PRIVATE

myBlendLayer.compositingFilter = “screenBlendMode"

myBlendLayer.allowsGroupOpacity = false

myLayer.addSublayer(myBlendLayer)

•注意:Private APIを利用している!

+ =

Page 35: try! Swift - Advanced Graphics with Core Animation

CALayer - “destIn” Blend ModeCALayer - “screenBlendMode” Blend

ModeCALayer - “linearLightBlendMode” Blend

ModeCAGradientLayer - “colorDodgeBlendMode” Blend

Mode

CALayer - “multiplyBlendMode” Blend Mode

CAShapeLayer - Normal Blend Mode

Page 36: try! Swift - Advanced Graphics with Core Animation

Reveal - http://revealapp.com

Page 37: try! Swift - Advanced Graphics with Core Animation

Animating with Core Animation

Page 38: try! Swift - Advanced Graphics with Core Animation

Compared to UIKit

let trySwiftView = UIImageView(image:)

let trySwiftView.center = CGPointZero

UIView.animateWithDuration(2, delay: 0, options: .CurveEaseInOut, animations: {

trySwiftView.center = CGPointMake(0, 500)

}, completion: nil)

Page 39: try! Swift - Advanced Graphics with Core Animation

CABasicAnimation

let trySwiftLayer = //…

let myAnimation = CABasicAnimation(keyPath: “position.x”)

myAnimation.duration = 2

myAnimation.fromValue = trySwiftLayer.position.x

myAnimation.toValue = trySwiftLayer.position.x + 500

myAnimation.timingFunction = kCAMediaTimingFunctionEaseInEaseOut

myAnimation.repeatCount = .infinity

trySwiftLayer.addAnimation(myAnimation, forKey: “myAnimationKeyName”)

Page 40: try! Swift - Advanced Graphics with Core Animation

CABasicAnimation

let trySwiftLayer = //…

let myAnimation = CABasicAnimation(keyPath: “position.x”)

myAnimation.duration = 2

myAnimation.fromValue = trySwiftLayer.position.x

myAnimation.toValue = trySwiftLayer.position.x + 500

myAnimation.timingFunction = kCAMediaTimingFunctionEaseInEaseOut

myAnimation.repeatCount = .infinity

trySwiftLayer.addAnimation(myAnimation, forKey: “myAnimationKeyName”)

Page 41: try! Swift - Advanced Graphics with Core Animation

Timing Function

let timingFunction = CAMediaTimingFunction(controlPoints: .08, .04, .08, .99)

let myAnimation = CABasicAnimation()

myAnimation.timingFunction = timingFunction

http://cubic-bezier.com

Page 42: try! Swift - Advanced Graphics with Core Animation

Animating a CALayer’s Contents

let imageView = UIImageView()

let onImage = UIImage()

let offImage = UIImage()

let myAnim = CABasicAnimation(keyPath: “contents”)

myAnim.fromValue = offImage.CGImage

myAnim.toValue = onImage.CGImage

myAnim.duration = 0.15

imageView.layer.addAnimation(myCrossfadeAnimation,

forKey: “contents”)

imageView.image = onImage

Page 43: try! Swift - Advanced Graphics with Core Animation

CAKeyframeAnimation

let rect = CGRectMake(0, 0, 200, 200)

let circlePath = UIBezierPath(ovalInRect:rect)

let circleAnimation = CAKeyframeAnimation()

circleAnimation.keyPath = “position”

circleAnimation.path = circlePath.CGPath

circleAnimation.duration = 4

// Manually specify keyframe points

// circleAnimation.values = //…

// circleAnimation.keyTimes = //..

let trySwiftLayer = //…

trySwiftLayer.addAnimation(circleAnimation,

forKey: “position”)

Page 44: try! Swift - Advanced Graphics with Core Animation

CAAnimationGroup

let myPositionAnimation = CABasicAnimation.animation(keyPath: “position”)

let myAlphaAnimation = CABasicAnimation.animation(keyPath: “opacity”)

let animationGroup = CAAnimationGroup()

animationGroup.timingFunction = kCAMediaTimingFunctionEaseInEaseOut

animationGroup.duration = 2

animationGroup.animations = [myPositionAnimation, myAlphaAnimation]

let trySwiftLayer = CALayer()

trySwiftLayer.addAnimation(animationGroup, forKey: “myAnimations”)

Page 45: try! Swift - Advanced Graphics with Core Animation

Animation Completion Handling

// Set a delegate object

let myAnimation = CABasicAnimation()

myAnimation.delegate = self

// Animation completion sent to ‘animationDidStop(anim: finished flag:)

// ———

//Set a closure to be executed at the end of this transaction

CATransaction.begin()

CATransaction.setCompletionBlock({

// Logic to be performed, post animation

})

CATransaction.commit()

Page 46: try! Swift - Advanced Graphics with Core Animation

CoreAnimator on the Mac App

Store

Page 47: try! Swift - Advanced Graphics with Core Animation

Features of Core Animation Subclasses

Page 48: try! Swift - Advanced Graphics with Core Animation

Features of Core Animation Subclasses

• UIViewのサブクラスで入れる

• GPUで実行、特別なイフェクト

•時々、CPUのオペレーションもある

public class MyGradientClass : UIView {

override class func layerClass() -> AnyClass {

return CAGradientLayer.self

}

}

Page 49: try! Swift - Advanced Graphics with Core Animation

CATileLayer

•色々なサイズで画像を再レン

ダー

• PDFやSVGやベクトルデータ

なら非常に役に立つ!

• Core Graphicsでバックグラウ

ンドで実行

Page 50: try! Swift - Advanced Graphics with Core Animation

CAGradientLayer

• GPUでグラジエントをレンダ

ーする

•3Dに変換されたレイヤで簡単に

影のエフェクト

Page 51: try! Swift - Advanced Graphics with Core Animation

CAReplicaterLayer

© iNVASIVECODE 2015

https://vimeo.com/128046096

• GPUで一つのレイヤを

何回もコピーして表示

する

•サムネールやゲームで

も役に立つ

Page 52: try! Swift - Advanced Graphics with Core Animation

CAShapeLayer

UAProgressView

© Urban Apps 2014

• CGPathから色々な形が表示

させ、アニメーションさせる

•読み込むアイコンにとても合って

•iOS 7のデザインスタイルにも似合って

Page 53: try! Swift - Advanced Graphics with Core Animation

CAEmitterLayer

Particle Playground on the Mac App Store

•レイヤの’frame’

からパーティクルが出る。

•ゲームやアプリ

の反応のアニメ

ーションに似合

う。

Page 54: try! Swift - Advanced Graphics with Core Animation

Other Layer Subclasses

•ゲームのためのCAEAGLLayer /

CAMetalLayer

•完全な3Dの変換のCATransformLayer

•大きなコンテンツをスクロールのCAScrollLayer

• UILabelと同じのようにCATextLayer

Page 55: try! Swift - Advanced Graphics with Core Animation

Conclusion

• UIなら、UIView直接じゃなく、CALayerだ

•もっと努力だから、最初にUIKitでやってみ

た方がいい

•ちゃんと使えば、60FPSでかっこういいエ

フェクトが可能性になる

•一緒に見事なアプリを作ろう!

Page 56: try! Swift - Advanced Graphics with Core Animation

Thanks for watching!

Page 57: try! Swift - Advanced Graphics with Core Animation

Thanks for watching!

[email protected] @TimOliverAU