/* The MIT License (MIT) Copyright (c) 2015 Yari D'areglia @bitwaker Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import UIKit public enum WalkthroughAnimationType:String{ case Linear = "Linear" case Curve = "Curve" case Zoom = "Zoom" case InOut = "InOut" init(_ name:String){ if let tempSelf = WalkthroughAnimationType(rawValue: name){ self = tempSelf }else{ self = .Linear } } } open class BWWalkthroughPageViewController: UIViewController, BWWalkthroughPage { private var animation:WalkthroughAnimationType = .Linear private var subviewsSpeed:[CGPoint] = Array() private var notAnimatableViews:[Int] = [] // Array of views' tags that should not be animated during the scroll/transition // MARK: Inspectable Properties // Edit these values using the Attribute inspector or modify directly the "User defined runtime attributes" in IB @IBInspectable var speed:CGPoint = CGPoint(x: 0.0, y: 0.0); // Note if you set this value via Attribute inspector it can only be an Integer (change it manually via User defined runtime attribute if you need a Float) @IBInspectable var speedVariance:CGPoint = CGPoint(x: 0.0, y: 0.0) // Note if you set this value via Attribute inspector it can only be an Integer (change it manually via User defined runtime attribute if you need a Float) @IBInspectable var animationType:String { set(value){ self.animation = WalkthroughAnimationType(rawValue: value)! } get{ return self.animation.rawValue } } @IBInspectable var animateAlpha:Bool = false @IBInspectable var staticTags:String { // A comma separated list of tags that you don't want to animate during the transition/scroll set(value){ self.notAnimatableViews = value.components(separatedBy: ",").map{Int($0)!} } get{ return notAnimatableViews.map{String($0)}.joined(separator: ",") } } @IBOutlet var mainView1: UIView! @IBOutlet var view1: UIView! @IBOutlet var view2: UIView! @IBOutlet var label1: UILabel! @IBOutlet var tit2: UILabel! @IBOutlet var label2: UILabel! @IBOutlet var mainView2: UIView! @IBOutlet var view3: UIView! @IBOutlet var view4: UIView! @IBOutlet var tit3: UILabel! @IBOutlet var label3: UILabel! @IBOutlet var tit4: UILabel! @IBOutlet var label4: UILabel! @IBOutlet var tit5: UILabel! @IBOutlet var mainView3: UIView! @IBOutlet var view5: UIView! @IBOutlet var label5: UILabel! @IBOutlet var view6: UIView! @IBOutlet var tit6: UILabel! @IBOutlet var label6: UILabel! @IBOutlet var mainView4: UIView! @IBOutlet var view7: UIView! @IBOutlet var tit7: UILabel! @IBOutlet var label7: UILabel! @IBOutlet var mainView5: UIView! @IBOutlet var view8: UIView! @IBOutlet var tit8: UILabel! @IBOutlet var label8: UILabel! @IBOutlet var mainView6: UIView! @IBOutlet var view9: UIView! @IBOutlet var tit9: UILabel! @IBOutlet var label9: UILabel! // MARK: BWWalkthroughPage Implementation override open func viewDidLoad() { super.viewDidLoad() var scale = self.view.frame.size.width/414 if (UIDevice.current.userInterfaceIdiom == .pad) { scale = self.view.frame.size.height/736 } if (mainView1 != nil) { view1.cornerRadius = 5 view1.applyGradient(colours: [grigio, UIColor.white]) view1.borderWidth = 2 view1.borderColor = grigioscuro2 view2.cornerRadius = 5 view2.applyGradient(colours: [grigio, UIColor.white]) view2.borderWidth = 2 view2.borderColor = grigioscuro2 view4.cornerRadius = 5 view4.applyGradient(colours: [grigio, UIColor.white]) view4.borderWidth = 2 view4.borderColor = grigioscuro2 //mainView1.transform = CGAffineTransform(scaleX: scale, y: scale) for constraint in mainView1.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view1.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view2.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view4.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } let fontSize = 18 * scale label1.font = UIFont(name: label1.font.fontName, size: fontSize) label2.font = UIFont(name: label1.font.fontName, size: fontSize) label4.font = UIFont(name: label4.font.fontName, size: fontSize) let fontSizeT = 20 * scale tit2.font = UIFont(name: tit2.font.fontName, size: fontSizeT) tit4.font = UIFont(name: tit4.font.fontName, size: fontSizeT) mainView1.layoutIfNeeded() } if (mainView3 != nil) { view5.cornerRadius = 5 view5.applyGradient(colours: [grigio, UIColor.white]) view5.borderWidth = 2 view5.borderColor = grigioscuro2 view6.cornerRadius = 5 view6.applyGradient(colours: [grigio, UIColor.white]) view6.borderWidth = 2 view6.borderColor = grigioscuro2 //mainView3.transform = CGAffineTransform(scaleX: scale, y: scale) for constraint in mainView3.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view5.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view6.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } let fontSize = 18 * scale label5.font = UIFont(name: label5.font.fontName, size: fontSize) label6.font = UIFont(name: label6.font.fontName, size: fontSize) let fontSizeT = 20 * scale tit5.font = UIFont(name: tit5.font.fontName, size: fontSizeT) tit6.font = UIFont(name: tit6.font.fontName, size: fontSizeT) } if (mainView4 != nil) { view7.cornerRadius = 5 view7.applyGradient(colours: [grigio, UIColor.white]) view7.borderWidth = 2 view7.borderColor = grigioscuro2 //mainView4.transform = CGAffineTransform(scaleX: scale, y: scale) for constraint in mainView4.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view7.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } let fontSize = 18 * scale label7.font = UIFont(name: label7.font.fontName, size: fontSize) let fontSizeT = 20 * scale tit7.font = UIFont(name: tit7.font.fontName, size: fontSizeT) } if (mainView5 != nil) { view8.cornerRadius = 5 view8.applyGradient(colours: [grigio, UIColor.white]) view8.borderWidth = 2 view8.borderColor = grigioscuro2 //mainView5.transform = CGAffineTransform(scaleX: scale, y: scale) for constraint in mainView5.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view8.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } let fontSize = 18 * scale label8.font = UIFont(name: label8.font.fontName, size: fontSize) let fontSizeT = 20 * scale tit8.font = UIFont(name: tit8.font.fontName, size: fontSizeT) } if (mainView6 != nil) { view9.cornerRadius = 5 view9.applyGradient(colours: [grigio, UIColor.white]) view9.borderWidth = 2 view9.borderColor = grigioscuro2 //mainView6.transform = CGAffineTransform(scaleX: scale, y: scale) for constraint in mainView6.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } for constraint in view9.constraints { if constraint.identifier == "const1" || constraint.identifier == "cost2" { constraint.constant = constraint.constant * scale } } let fontSize = 18 * scale label9.font = UIFont(name: label9.font.fontName, size: fontSize) let fontSizeT = 20 * scale tit9.font = UIFont(name: tit9.font.fontName, size: fontSizeT) } self.view.layer.masksToBounds = true subviewsSpeed = Array() for v in view.subviews{ speed.x += speedVariance.x speed.y += speedVariance.y if !notAnimatableViews.contains(v.tag) { subviewsSpeed.append(speed) } } } override open func viewWillAppear(_ animated: Bool) { } open func walkthroughDidScroll(to: CGFloat, offset: CGFloat) { for i in 0 ..< subviewsSpeed.count{ // Perform animations switch animation{ case .Linear: animationLinear(i, offset) case .Zoom: animationZoom(i, offset) case .Curve: animationCurve(i, offset) case .InOut: animationInOut(i, offset) } // Animate alpha if(animateAlpha){ animationAlpha(i, offset) } } } // MARK: Animations private func animationAlpha(_ index:Int, _ offset:CGFloat) { let cView = view.subviews[index] var mutableOffset = offset if(mutableOffset > 1.0){ mutableOffset = 1.0 + (1.0 - mutableOffset) } cView.alpha = (mutableOffset) } private func animationCurve(_ index:Int, _ offset:CGFloat) { var transform = CATransform3DIdentity let x:CGFloat = (1.0 - offset) * 10 transform = CATransform3DTranslate(transform, (pow(x,3) - (x * 25)) * subviewsSpeed[index].x, (pow(x,3) - (x * 20)) * subviewsSpeed[index].y, 0 ) applyTransform(index, transform: transform) } private func animationZoom(_ index:Int, _ offset:CGFloat){ var transform = CATransform3DIdentity var tmpOffset = offset if(tmpOffset > 1.0){ tmpOffset = 1.0 + (1.0 - tmpOffset) } let scale:CGFloat = (1.0 - tmpOffset) transform = CATransform3DScale(transform, 1 - scale , 1 - scale, 1.0) applyTransform(index, transform: transform) } private func animationLinear(_ index:Int, _ offset:CGFloat) { var transform = CATransform3DIdentity let mx:CGFloat = (1.0 - offset) * 100 transform = CATransform3DTranslate(transform, mx * subviewsSpeed[index].x, mx * subviewsSpeed[index].y, 0 ) applyTransform(index, transform: transform) } private func animationInOut(_ index:Int, _ offset:CGFloat) { var transform = CATransform3DIdentity var tmpOffset = offset if(tmpOffset > 1.0){ tmpOffset = 1.0 + (1.0 - tmpOffset) } transform = CATransform3DTranslate(transform, (1.0 - tmpOffset) * subviewsSpeed[index].x * 100, (1.0 - tmpOffset) * subviewsSpeed[index].y * 100, 0) applyTransform(index, transform: transform) } private func applyTransform(_ index:Int, transform:CATransform3D){ let subview = view.subviews[index] if !notAnimatableViews.contains(subview.tag){ view.subviews[index].layer.transform = transform } } }