1. 程式人生 > >[Swift通天遁地]九、拔劍吧-(14)創建更美觀的景深視差滾動效果

[Swift通天遁地]九、拔劍吧-(14)創建更美觀的景深視差滾動效果

forward 對數 etl tween () mage 初始 lambda 演示

景深視差經常被應用在遊戲項目中。

本文將演示創建更美觀的景深視差滾動效果。

首先確保已經安裝了所需的第三方類庫。雙擊查看安裝配置文件【Podfile】

1 platform :ios, 12.0
2 use_frameworks!
3 
4 target DemoApp do
5     source https://github.com/CocoaPods/Specs.git
6     pod Presentation
7 end

根據配置文件中的相關設置,安裝第三方類庫。

安裝完成之後,雙擊打開項目文件【DemoApp.xcodeproj】

在左側的項目導航區,打開視圖控制器的代碼文件【ViewController.swift】

  1 import UIKit
  2 //引入已經安裝的第三方類庫
  3 import Presentation
  4 
  5 //修改當前類的父類,這裏使用第三方類庫提供的父類
  6 class ViewController: PresentationController {
  7 
  8     //添加一個結構體類型,
  9     //用來更加方便的管理背景視圖中的視差圖片,
 10     //四個屬性依次表示:
 11     struct BackgroundImage
 12     {
 13         //圖片的名稱
 14         let name: String
15 //水平初始位置 16 let left: CGFloat 17 //垂直初始位置 18 let top: CGFloat 19 //滾動的速度 20 let speed: CGFloat 21 22 //添加一個初始化方法,用來初始化結構體的各個屬性。 23 init(name: String, left: CGFloat, top: CGFloat, speed: CGFloat) 24 { 25 //
依次設置各個屬性的值 26 self.name = name 27 self.left = left 28 self.top = top 29 self.speed = speed 30 } 31 32 //添加一個方法,用來獲取當滾動到某個頁面時到位置屬性 33 func positionAt(_ index: Int) -> Position? 34 { 35 //添加一個位置變量 36 var position: Position? 37 38 //判斷當前是否時是需要顯示滾動效果的頁面。 39 if index == 0 || speed != 0.0 40 { 41 //根據起始位置、當前頁面的序號、計算當前頁面的視差圖片的水平位置。 42 let currentLeft = left + CGFloat(index) * speed 43 //設置視差圖片的新的位置,視差圖片的垂直坐標,是保持不變的。 44 position = Position(left: currentLeft, top: top) 45 } 46 47 //返回設置好的位置 48 return position 49 } 50 } 51 52 //添加一個導航條按鈕控件,作為導航條左側的按鈕 53 lazy var leftButton: UIBarButtonItem = 54 { [unowned self] in 55 56 //對導航條按鈕進行初始化操作,並設置它的標題、樣式和動作屬性。 57 let leftButton = UIBarButtonItem(title: "Previous", style: .plain, 58 target: self, action: #selector(moveBack)) 59 60 //設置標題的前景顏色為黑色 61 leftButton.setTitleTextAttributes( 62 [NSAttributedString.Key.foregroundColor : UIColor.black], for: .normal) 63 64 //返回設置好的按鈕控件 65 return leftButton 66 }() 67 68 //創建另一個導航條按鈕控件,作為導航條右側的按鈕。 69 lazy var rightButton: UIBarButtonItem = 70 { [unowned self] in 71 72 //對導航條按鈕k進行初始化操作,並設置它的標題、樣式和動作屬性。 73 let rightButton = UIBarButtonItem(title: "Next", style: .plain, 74 target: self, action: #selector(moveForward)) 75 76 //設置標題文字的前景顏色為黑色。 77 rightButton.setTitleTextAttributes( 78 [NSAttributedString.Key.foregroundColor : UIColor.black], for: .normal) 79 80 //返回設置好的按鈕控件。 81 return rightButton 82 }() 83 84 override func viewDidLoad() { 85 super.viewDidLoad() 86 // Do any additional setup after loading the view, typically from a nib. 87 88 //依次設置導航控制器左側和右側的導航按鈕。 89 navigationItem.leftBarButtonItem = leftButton 90 navigationItem.rightBarButtonItem = rightButton 91 92 //設置根視圖的背景顏色。 93 view.backgroundColor = UIColor(red: 1.0, green: 188.0/255, blue: 0, alpha: 1) 94 95 //調用兩個方法: 96 //方法一:用來設置滾動的標題 97 configureSlides() 98 //方法二:用來設置具有景深效果的背景視圖。 99 configureBackground() 100 } 101 102 //添加一個方法,用來配置滾動標題 103 func configureSlides() 104 { 105 //初始一個字體對象 106 let font = UIFont(name: "HelveticaNeue", size: 24.0)! 107 //初始化一個顏色對象 108 let color = UIColor(red: 1.0, green: 232.0/255, blue: 169.0/255, alpha: 1) 109 //作為標題文字的字體和顏色。 110 111 //初始化一個段落樣式對象 112 let paragraphStyle = NSMutableParagraphStyle() 113 //設置段落樣式的對齊方式為居中 114 paragraphStyle.alignment = NSTextAlignment.center 115 116 //初始化一個屬性常量,作為標題文字的字體、顏色和段落樣式。 117 let attributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: color, .paragraphStyle: paragraphStyle] 118 119 //初始化一個字符串數組,作為五個滾動標題的內容。 120 let titles = [ 121 "Parallax is a displacement or difference in the apparent position of an object viewed along two different lines of sight.", 122 "It‘s measured by the angle or semi-angle of inclination between those two lines.", 123 "The term is derived from the Greek word παρ?λλαξις (parallaxis), meaning ‘alteration‘.", 124 "Nearby objects have a larger parallax than more distant objects when observed from different positions.", 125 "http://www.coolketang.com"] 126 //對標題數組進行遍歷,設置標題的樣式 127 .map 128 { title -> Content in 129 //初始化一個標簽對象, 130 let label = UILabel(frame: CGRect(x: 0, y: 0, width: 550, height: 200)) 131 //設置標簽對象最多顯示的行數 132 label.numberOfLines = 5 133 //設置標簽對象顯示的文字內容,和文字的外觀樣式。 134 label.attributedText = NSAttributedString(string: title, attributes: attributes) 135 //初始化一個位置對象 136 let position = Position(left: 0.0, top: 0.35) 137 138 //使用標簽和位置初始化一個內容對象,並返回內容對象作為頁面的標題 139 return Content(view: label, position: position) 140 } 141 142 //初始化一個滑動控制器類型的數組對象。 143 var slides = [SlideController]() 144 145 //添加一個執行五次的循環語句,用來往數組中添加控制器。 146 for index in 0...(titles.count - 1) 147 { 148 //初始化一個滑動控制器對象,並設置它的標題內容 149 let controller = SlideController(contents: [titles[index]]) 150 //往滑動控制器中,添加一個標題滾動的動畫。 151 controller.add(animations: [Content.centerTransition(forSlideContent: titles[index])]) 152 153 if(index == titles.count - 1) 154 { 155 controller.setLast() 156 } 157 158 //將配置好的滑動控制器,添加到數組中。 159 slides.append(controller) 160 } 161 162 //將滑動控制器數組添加到景深視圖控制器中。 163 add(slides) 164 } 165 166 //添加另一個方法,用來配置具有景深效果的背景視圖。 167 func configureBackground() 168 { 169 //初始化一個圖像視圖數組,作為背景視圖中的視差圖片。 170 let backgroundImages = 171 [ 172 //往數組中,依次添加同結構體類型,生成的九張視差圖片, 173 //並設置每張視查圖片的名稱、位置、和速度等屬性。 174 BackgroundImage(name: "Trees", left: 0.0, top: 0.743, speed: -0.3), 175 BackgroundImage(name: "Bus", left: 0.02, top: 0.77, speed: 0.25), 176 BackgroundImage(name: "Truck", left: 1.3, top: 0.73, speed: -1.5), 177 BackgroundImage(name: "Roadlines", left: 0.0, top: 0.79, speed: -0.24), 178 BackgroundImage(name: "Houses", left: 0.0, top: 0.627, speed: -0.16), 179 BackgroundImage(name: "Hills", left: 0.0, top: 0.51, speed: -0.08), 180 BackgroundImage(name: "Mountains", left: 0.0, top: 0.29, speed: 0.0), 181 BackgroundImage(name: "Clouds", left: -0.415, top: 0.14, speed: 0.18), 182 BackgroundImage(name: "Sun", left: 0.8, top: 0.07, speed: 0.0) 183 ] 184 185 //添加一個內容類型的數組。 186 var contents = [Content]() 187 188 //對視差圖片數組進行遍歷,從而創建九個視差內容, 189 //並放置在數組中。 190 for backgroundImage in backgroundImages 191 { 192 //從指定的結構體中,獲得圖片的名稱,然後初始化一個指定圖片名稱的圖像視圖。 193 let imageView = UIImageView(image: UIImage(named: backgroundImage.name)) 194 //獲得結構體中的視差圖片的位置。 195 if let position = backgroundImage.positionAt(0) 196 { 197 //初始化一個指定視圖、位置和中心點屬性的視差內容。然後將視差內容添加到數組中。 198 contents.append(Content(view: imageView, position: position, centered: false)) 199 } 200 } 201 202 //將所有的視差內容添加到背景視圖中 203 addToBackground(contents) 204 205 //添加另一個執行五次的循環語句,給每個頁面添加一個視差動畫。 206 for row in 1...4 207 { 208 //對數組中的視差內容進行遍歷 209 for (column, backgroundImage) in backgroundImages.enumerated() 210 { 211 //獲得視差內容,以及視差內容的當前位置。 212 if let position = backgroundImage.positionAt(row), let content = contents.at(column) 213 { 214 //初始化一個過渡動畫對象,並設置動畫對象的視差內容、目標位置、動畫時長和阻尼值 215 addAnimation(TransitionAnimation(content: content, destination: position, duration: 2.0, damping: 1.0), forPage: row) 216 } 217 } 218 } 219 220 //創建一個指定顯示區域的視圖對象,作為視差背景的地面視圖 221 let groundView = UIView(frame: CGRect(x: 0, y: 0, width: 1024, height: 60)) 222 //設置地面視圖的背景顏色, 223 groundView.backgroundColor = UIColor(red: 1.0, green: 205.0/255, blue: 65/255.0, alpha: 1.0) 224 //將地面視圖轉換成一個內容對象,並設置它的位置。 225 let groundContent = Content(view: groundView, 226 position: Position(left: 0.0, bottom: 0.063), centered: false) 227 //將地面內容對象也添加到數組中。 228 contents.append(groundContent) 229 230 //將內容數組添加到背景視圖。 231 addToBackground([groundContent]) 232 } 233 } 234 235 //添加一個針對數組類型的擴展。 236 extension Array 237 { 238 //添加一個擴展方法,用來獲得在數組中指定位置的元素。 239 func at(_ index: Int?) -> Element? 240 { 241 //創建一個元素變量。 242 var object: Element? 243 //當元素位置在數組長度範圍之內時,根據下標獲得數組中的元素。 244 if let index = index , index >= 0 && index < endIndex 245 { 246 object = self[index] 247 } 248 249 //返回獲得的元素 250 return object 251 } 252 }

在左側的項目導航區,打開應用程序的代理文件【AppDelegate.swift

在應用程序加載完成的方法中,創建一個導航控制器。

 1 import UIKit
 2 
 3 @UIApplicationMain
 4 class AppDelegate: UIResponder, UIApplicationDelegate {
 5 
 6     var window: UIWindow?
 7 
 8     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
 9         // Override point for customization after application launch.
10         
11         //清除導航條在默認狀態下的背景圖片
12         UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
13         //清除導航條的陰影圖片
14         UINavigationBar.appearance().shadowImage = UIImage()
15         
16         //多上文創建的視圖控制器進行初始化操作。
17         let vc = ViewController(pages: [])
18         //創建一個導航控制器,並設置導航控制器的根視圖控制器
19         let navigationController = UINavigationController(rootViewController: vc)
20         //設置窗口對象的根視圖控制器,為導航控制器。
21         window?.rootViewController = navigationController
22          //並將窗口對象作為應用程序的主窗口。
23         window?.makeKeyAndVisible()
24 
25         return true
26     }
27 
28     func applicationWillResignActive(_ application: UIApplication) {
29         // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
30         // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
31     }
32 
33     func applicationDidEnterBackground(_ application: UIApplication) {
34         // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
35         // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
36     }
37 
38     func applicationWillEnterForeground(_ application: UIApplication) {
39         // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
40     }
41 
42     func applicationDidBecomeActive(_ application: UIApplication) {
43         // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
44     }
45 
46     func applicationWillTerminate(_ application: UIApplication) {
47         // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48     }
49 }

[Swift通天遁地]九、拔劍吧-(14)創建更美觀的景深視差滾動效果