407 Views
October 09, 13
スライド概要
2023年10月からSpeaker Deckに移行しました。最新情報はこちらをご覧ください。 https://speakerdeck.com/lycorptech_jp
魅せるUIの作り方 iOS 7 エンジニア勉強会@ヤフー 2013/10/7 カカオジャパン 佐藤新悟
iOS 7 らしい UI • フラットデザイン、それだけ? • 物理法則にもとづいたリアルなアニ メーション • 視差を利用した奥行きの表現 • 磨りガラスのような透過表現
UIKit Dynamics • UIKitのための2次元物理エンジン • これまでのアニメーションの仕組みを 置き換えるものではない • ゲームのためのものではない(Sprite Kitを使おう)
Demo
Gravity and Collision UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[square1,square2]]; UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[square1,square2]]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; [animator addBehavior:gravityBeahvior]; [animator addBehavior:collisionBehavior];
Architecture UIDynamicAnimator Reference View UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
Architecture Superview Subview Subview Subview
UIDynamicBehavior • UIGravityBehavior • UICollisionBehavior • UIAttachmentBehavior • UISnapBehavior • UIPushBehavior • UIDynamicItemBehavior
Demo
UIGravityBehavior • 重力の強さと方向を設定可能 UIGravityBehavior* gravityBeahavior = [[UIGravityBehavior alloc] initWithItems:@[self.square1]]; gravityBeahavior.gravityDirection = CGVectorMake(0.0f, 1.0f); gravityBeahavior.magnitude = 1.0f; gravityBeahavior.angle = -M_PI/2.0;
UICollisionBehavior UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems: @[self.square1, self.square2]]; collisionBehavior.collisionMode = UICollisionBehaviorModeEverything; // UICollisionBehaviorModeBoundaries, UICollisionBehaviorModeItems CGPoint p0; CGPoint p1; [collisionBehavior addBoundaryWithIdentifier:@"b0" fromPoint:p0 toPoint:p1]; UIBezierPath *path; [collisionBehavior addBoundaryWithIdentifier:@"b1" forPath:path]; • view同士の衝突も可能 • CGPointで直線を指定、またはUIBezierPath を使って境界を追加可能
UIAttachmentBehavior CGPoint anchorPoint = CGPointMake(self.square1.center.x, self.square1.center.y - 100.0); UIOffset offset = UIOffsetMake(-25.0, -25.0); UIAttachmentBehavior* attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.square1 offsetFromCenter:offset attachedToAnchor:anchorPoint]; attachmentBehavior.frequency = 1.0; attachmentBehavior.damping = 0.1; • view上の点と指定した点を繋ぐ • バネのように伸び縮みさせることもできる
UISnapBehavior UISnapBehavior* snapBehavior = [[UISnapBehavior alloc] initWithItem:self.square1 snapToPoint:point]; • viewを指定した点に吸い付くようにする
UIPushBehavior typedef NS_ENUM(NSInteger, UIPushBehaviorMode) { UIPushBehaviorModeContinuous, UIPushBehaviorModeInstantaneous } UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.square1] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = 0.0; pushBehavior.magnitude = 1.0; • 瞬間的に力を加える instantaneous と、継続 的に力を加える continuous のモードがある • 力の方向と強さを設定可能
UIDynamicItemBehavior UIDynamicItemBehavior* propertiesBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.square1]]; propertiesBehavior.elasticity = 0.5; • 指定したviewの特性を変える • elasticity: 弾性 • friction: 摩擦 • density: 密度(質量) • resistance: 抵抗 • angularResistance: 回転に対する抵抗 • allowsRotation: itemの回転を許すか否か
Motion Effects • 端末の傾きに応じて視差効果を与える
Motion Effects
UIMotionEffect UIInterpolatingMotionEffect *xAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; xAxis.minimumRelativeValue = @(-20.0f); xAxis.maximumRelativeValue = @20.0f; UIInterpolatingMotionEffect *yAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; yAxis.minimumRelativeValue = @(-20.0f); yAxis.maximumRelativeValue = @20.0f; UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init]; group.motionEffects = @[xAxis, yAxis]; [self.button addMotionEffect:group];
Blur Effect
Blur Effect • UIKit標準のコントロールは背景をぼかして透過する処 理を自動で行う • APIは公開されていないので独自のviewで同じことをや るには自力で実装が必要 • WWDCのサンプルコードとしてUIImageのカテゴリが 配布されている (UIImage+ImageEffects) • 静止画を作るだけなので動的なコンテンツへの利用 は難しい • 静止画だけでも工夫次第でできることは多い
Demo
Blur Effect // viewのスナップショットを撮る UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0); [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO]; UIImage *bgImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // blurをかける bgImage = [bgImage applyLightEffect]; • -[CALayer renderInContext:] よりも高速
(B) 降りてくるview clipsToBounds = YES (A) 背景view (C) blurred image Bのsubview B の動きに合わせて C のframeを調整して 動かないように見せる
まとめ • 物理法則にもとづいたリアルなアニメーション → UIKit Dynamics • 視差を利用した奥行きの表現 → Motion Effects • 磨りガラスのような透過表現 • • UIKit標準コントロールを利用 自前実装はパフォーマンスに注意
参考資料 • UIKit Dynamics Catalog • WWDC 2013 sessions https://developer.apple.com/library/ios/samplecode/DynamicsCatalog https://developer.apple.com/wwdc/videos/ • • • • Getting Started with UIKit Dynamics Advanced Techniques with UIKit Dynamics Implementing Engaging UI on iOS (Motion Effects, Snapshot, Blur) WWDC 2013 Sample Codes https://developer.apple.com/wwdc/resources/ • • iOS̲RunningWithASnap iOS̲UIImageEffects (ぼかし用UIImageカテゴリ)